Mozilla 说 Web components由三项主要技术组成:
是第 3 项,“HTML 模板”,根据 ECMAscript 的 Template Literals 甚至是必要的?
看看我从 James Milner 得到的这个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Web Component</title>
<script type="text/javascript">
// We define an ES6 class that extends HTMLElement
class CounterElement extends HTMLElement{
constructor() {
super();
// Initialise the counter value
this.counter = 0;
// We attach an open shadow root to the custom element
const shadowRoot= this.attachShadow({mode: 'open'});
// We define some inline styles using a template string
const styles=`
:host {
position: relative;
font-family: sans-serif;
}
#counter-increment, #counter-decrement {
width: 60px;
height: 30px;
margin: 20px;
background: none;
border: 1px solid black;
}
#counter-value {
font-weight: bold;
}
`;
// We provide the shadow root with some HTML
shadowRoot.innerHTML = `
<style>${styles}</style>
<h3>Counter</h3>
<slot name='counter-content'>Button</slot>
<button id='counter-increment'> - </button>
<span id='counter-value'> 0 </span>
<button id='counter-decrement'> + </button>
`;
// We can query the shadow root for internal elements
// in this case the button
this.incrementButton = this.shadowRoot.querySelector('#counter-increment');
this.decrementButton = this.shadowRoot.querySelector('#counter-decrement');
this.counterValue = this.shadowRoot.querySelector('#counter-value');
// We can bind an event which references one of the class methods
this.incrementButton.addEventListener("click", this.decrement.bind(this));
this.decrementButton.addEventListener("click", this.increment.bind(this));
}
increment() {
this.counter++
this.invalidate();
}
decrement() {
this.counter--
this.invalidate();
}
// Call when the counter changes value
invalidate() {
this.counterValue.innerHTML = this.counter;
}
}
// This is where the actual element is defined for use in the DOM
customElements.define('counter-element', CounterElement);
</script>
</head>
<body>
<counter-element></counter-element>
</body>
</html>
注意他如何不使用 HTML 模板,而是使用 ecmascript 模板文字来设置 shadowRoot 的 innerHTML。
在此之后,他使用 querySelector 获取 shadowRoot 的内部元素,并最终将事件监听器添加到递增和递减按钮。
如果您要使用 HTML 模板而不是 ecmascript 模板文字,这对您有什么好处?
从概念上讲,我正在努力寻找一种我更喜欢 HTML 模板元素而不是 Ecmascript 模板文字的情况。
请指教。
最佳答案
模板标签对于 Web 组件本身并不是“必需的”。当 HTML Imports 时可能更有意义正在插入,允许导入和重用 HTML 片段,但此后已停止。在这里您可以导入一个模板并重新使用它。
重要的是要注意这些规范是独立设计的,也可以相互依赖地使用,这使得它们具有通用性。 HTML 标签在 Web 组件领域之外有用例;它很有用,因为它允许您定义一段标记,该标记在稍后通过 JavaScript 实例化之前不会呈现。事实上,您可以在不使用任何其他规范(自定义元素、Shadow DOM 等)的情况下使用模板。
模板标签当然可以与其他规范一起使用。例如,我们可以在所示示例中使用它来使代码的命令性降低,而使标记更加集中,如下所示:
<template id="counterTemplate">
<style>
:host {
position: relative;
font-family: sans-serif;
}
#counter-increment, #counter-decrement {
width: 60px;
height: 30px;
margin: 20px;
background: none;
border: 1px solid black;
}
#counter-value {
font-weight: bold;
}
</style>
<h3>Counter</h3>
<slot name='counter-content'>Button</slot>
<button id='counter-increment'> - </button>
<span id='counter-value'> 0 </span>
<button id='counter-decrement'> + </button>
</template>
然后像这样在 JavaScript 中使用它:
const template = document.querySelector('#counterTemplate');
const counter = document.cloneNode(template);
shadowRoot.appendChild(counter);
这里的缺点是它需要模板在实例化之前存在于 DOM 中,因为它依赖于 #counterTemplate 模板。在某些方面,这会降低自定义元素的可移植性,因此模板文字可能更受欢迎。我没有测试过两者的性能,但我的直觉告诉我,该模板的性能可能更高。
免责声明:我写了原始博文
关于javascript - HTML <template> 元素与 Javascript 模板文字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53311660/