Как реализовать lit-html вместо juicy-html в компоненте полимера 3? - PullRequest
0 голосов
/ 29 сентября 2018

Я конвертирую приложение из полимера 1 в полимер 3. Я использовал juicy-html, но они не обновились до Polymer 3, и я вижу, что есть lit-html.Мне интересно, как я могу изменить этот фрагмент на использование lit-html.Он используется для расширения строки, например: 'Hello <span class="highlight">world</span>!'

Вот фрагмент кода из моего компонента полимера 1.

<template is="dom-repeat" items="[[item.snippets]]">
  <template is="dom-repeat" items="[[item.matches]]">
    <div><template is="juicy-html" content$="[[item.text]]"></template></div>
  </template>
</template>

Нужно ли реализовывать новый компонент для внутреннегоDIV?Есть ли пример, который я могу посмотреть?

Вот результирующий элемент Polymer 3 для отображения выделенного текста в строке:

import {html, LitElement} из '@ Polymer / lit-element / lit-element.js ';

/**
 * `search-snippet-highlight`
 * 
 *
 * @customElement
 * @polymer
 * @demo demo/index.html
 */
class SearchSnippetHighlight extends LitElement {

  static get properties() {
    return {
      snippet: { type: String }
    };
  }

  render() {
    return html`
      <style>.highlight { background-color: yellow; }</style>
      <div .innerHTML="${this.sanitizeHtml(this.snippet)}"></div>`;
  }

  sanitizeHtml(input) {
    return input; // TODO: actually sanitize input with sanitize-html library
  }

}

window.customElements.define('search-snippet-highlight', SearchSnippetHighlight);

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Я добавил это в ответ, поскольку @ tony19 предполагал, что его можно правильно отформатировать.Я на самом деле не задавал отдельный вопрос, на самом деле просто задавал риторический вопрос, а не предлагал отдельное решение.

Вы можете немного упростить подход, так как подсвеченный позволяет вам создавать HTML в слоях черезmap function.

render() {    
    return html`
        <div>${this.item.snippets.map(s => s.matches.map(m => 
                html`<div>${this.sanitizeHtml(m.text)}</div>`
            ))}
       </div>
    `; 
}

Теперь одна проблема с этим (и принятым ответом) заключается в том, что при каждом рендеринге вы пересчитываете все это, включая очистку HTML.lit-html имеет директиву guard, которая может помочь с этим.Добавление этого обеспечит повторный рендеринг только при изменении.

render() {    
    return html`
        <div>${guard(this.item.snippets, () => this.item.snippets.map(s => 
                 guard(s.matches, () => s.matches.map(m => 
                html`<div>${this.sanitizeHtml(m.text)}</div>`
            ))))}
       </div>
    `; 
}

Это требует от вас определенной дисциплины в отношении того, как this.item.snippets и базовый matches обновляются.Необходимо убедиться, что используемые ссылки «Массив» изменяются при обновлении.Примерно так (при условии, что совпадения обновляются с новым совпадением), sindex - это индекс snippet, который вы хотите обновить, и mindex - это индекс match в пределах этого snippet, которым вы являетесь.обновление с newMatch;

this.items.snippets = this.items.snippets.map((snippet, index) => index === sindex ?
   {...snippet, matches: snippet.matches.map((match, index) => index === mindex ?
      newMatch : match)} : snippet);
0 голосов
/ 30 сентября 2018

Эквивалент этого <template> с juicy-html в Polymer's LitElement (рекомендуемый базовый элемент, который использует lit-html):

render() {
  let content = '';
  for (const s of this.item.snippets) {
    for (const m of s.matches) {
      content += `<div>${m.text}</div>`;
    }
  }
  return html`<div .innerHTML="${this.sanitizeHtml(content)}"></div>`;
}

render указанная выше функция выполняет следующие действия:

  1. создает строку HTML из входных данных
  2. очищает HTML
  3. помещает результат в контейнер div innerHTML, с использованием синтаксиса LitElement (.PROPERTY="VALUE")

<html>
<head>
  <!-- Polyfills only needed for Firefox and Edge. -->
  <script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
</head>
<body>
  <!-- Works only on browsers that support Javascript modules like
       Chrome, Safari, Firefox 60, Edge 17 -->
  <script type="module">
    import {LitElement, html} from 'https://unpkg.com/@polymer/lit-element/lit-element.js?module';

    class MyElement extends LitElement {

      static get properties() {
        return {
          item: { type: Object }
        }
      }

      constructor() {
        super();
        this.item = {
          snippets: [
            {
              matches: [
                {text: 'hello <span class="highlight">world</span>'},
                {text: 'we are the <span class="highlight">world</span>'},
                {text: 'war of the <span class="highlight">world</span>s'},
              ]
            },
            {
              matches: [
                {text: 'the <span class="highlight">cat</span> in the hat'},
                {text: '<span class="highlight">cat</span>fish are in the water'},
                {text: '<span class="highlight">cat</span>erpillars become butterflies'},
              ]
            },
          ]
        };
      }

      render() {
        let content = '';
        for (const s of this.item.snippets) {
          for (const m of s.matches) {
            content += `<div>${m.text}</div>`;
          }
        }
        return html`
          <style>.highlight { background: rgb(255, 251, 222); }</style>
          <div .innerHTML="${this.sanitizeHtml(content)}"></div>`;
      }

      sanitizeHtml(input) {
        return input; // TODO: actually sanitize input with sanitize-html library
      }
    }

    customElements.define('my-element', MyElement);
  </script>
  
  <my-element mood="great"></my-element>
  
</body>
</html>
...