为什么需要模板?

Permalink to "为什么需要模板?"

使用未做任何清理的 innerHTML 和模板字符串可能会导致脚本注入的安全问题。过去,开发者使用各种变通方法来实现 HTML 模板,但这些变通方法都存在问题。

这就是 <template> 元素发挥作用的地方;模板提供了真正的惰性 DOM、一种高性能的节点克隆方法以及可复用的模板功能。

使用模板

Permalink to "使用模板"

接下来,将组件转换为使用 HTML 模板:

index.html

Permalink to "index.html"
<body>
<template id="rating-element-template">
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating"></span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
</template>

<rating-element>
<div>
This is the light DOM!
</div>
</rating-element>
</body>

这里你将 DOM 内容移到了主文档 DOM 中的 <template> 标签里。现在重构自定义元素的定义:

rating-element.

Permalink to "rating-element."
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
const templateContent = document.querySelector<HTMLTemplateElement>('#rating-element-template')!.content;
const clonedContent = templateContent.cloneNode(true);
shadowRoot.appendChild(clonedContent);

this.shadowRoot!.querySelector<HTMLElement>('.rating')!.innerText = `${this.rating}`;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
const templateContent = document.querySelector('#rating-element-template').content;
const clonedContent = templateContent.cloneNode(true);
shadowRoot.appendChild(clonedContent);

this.shadowRoot.querySelector('.rating').innerText = `${this.rating}`;
}

使用这个 <template> 元素的步骤:

  1. 查询模板。
  2. 获取其内容。
  3. 使用 templateContent.cloneNode 克隆这些节点。
  4. 使用数据初始化 DOM。

恭喜,现在你的 Web Component 的 DOM 已经被封装了,但 DOM 仍然是静态的。在接下来的步骤中,你将添加更新评分的支持。