如何在聚合物 3 组件中实现 lit-html 而不是 juicy-html?
How to implement lit-html instead of juicy-html in a polymer 3 component?
我正在将一个应用程序从 polymer 1 转换为 polymer 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 元素,用于在字符串中显示突出显示的文本:
从'@polymer/lit-element/lit-element.js'导入{html, LitElement};
/**
* `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);
在 Polymer 的 LitElement
(推荐使用 lit-html
的基本元素)中 <template>
和 juicy-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
函数执行以下操作:
- 从输入构建一个 HTML 字符串
- 清理 HTML
- 将结果放入容器
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>
我把它放在一个答案中,因为 @tony19 建议它可以正确格式化。我并不是真的在问一个单独的问题,实际上只是在问一个修辞性的问题,而不是提供一个单独的解决方案。
您可以大大简化该方法,因为 lit 允许您通过 map
函数分层构建 html。
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
的更新方式施加一些约束。您必须确保正在使用的 "Array" 引用在有更新时发生变化。像这样的东西(假设匹配项正在用新匹配项更新)并且 sindex
是您要更新的 snippet
的索引,而 mindex
是 [=21= 的索引] 在 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);
我正在将一个应用程序从 polymer 1 转换为 polymer 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 元素,用于在字符串中显示突出显示的文本:
从'@polymer/lit-element/lit-element.js'导入{html, LitElement};
/**
* `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);
在 Polymer 的 LitElement
(推荐使用 lit-html
的基本元素)中 <template>
和 juicy-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
函数执行以下操作:
- 从输入构建一个 HTML 字符串
- 清理 HTML
- 将结果放入容器
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>
我把它放在一个答案中,因为 @tony19 建议它可以正确格式化。我并不是真的在问一个单独的问题,实际上只是在问一个修辞性的问题,而不是提供一个单独的解决方案。
您可以大大简化该方法,因为 lit 允许您通过 map
函数分层构建 html。
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
的更新方式施加一些约束。您必须确保正在使用的 "Array" 引用在有更新时发生变化。像这样的东西(假设匹配项正在用新匹配项更新)并且 sindex
是您要更新的 snippet
的索引,而 mindex
是 [=21= 的索引] 在 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);