HTML <template> 元素与 Javascript 模板文字

Lon*_*est 7 javascript web-component template-literals hyperhtml html-templates

Mozilla 表示Web 组件由三种主要技术组成:

  1. 自定义元素
  2. 影子DOM
  3. HTML 模板

根据 ECMAscript 的模板文字,数字 3,“HTML 模板”甚至是必要的吗?

看看我从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>
Run Code Online (Sandbox Code Playgroud)

请注意他如何不使用 HTML 模板,而是使用 ecmascript 模板文字来设置 shadowRoot 的 innerHTML。

此后,他使用 querySelector 获取 shadowRoot 的内部元素,并最终将事件侦听器添加到增量和减量按钮。

如果您要使用 HTML 模板,而不是 ecmascript 模板文字,这对您有什么好处?

从概念上讲,我正在努力寻找一种情况,即我更喜欢 HTML 模板元素而不是 Ecmascript 模板文字。

请指教。

Jam*_*ner 3

模板标签对于 Web 组件本身来说并不是“必需的”。当HTML 导入被推送时,它可能更有意义,允许导入和重用 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>
Run Code Online (Sandbox Code Playgroud)

然后稍后在 JavaScript 中使用它,如下所示:

   const template = document.querySelector('#counterTemplate');
   const counter = document.cloneNode(template);
   shadowRoot.appendChild(counter);
Run Code Online (Sandbox Code Playgroud)

这里的缺点是,它要求模板在实例化之前就存在于 DOM 中,因为它依赖于那里的 #counterTemplate 模板。在某些方面,这使得自定义元素的可移植性较差,因此模板文字可能更可取。我还没有测试两者的性能,但我的直觉告诉我,该模板可能会性能更高。

免责声明:我写了原始博客文章