Element-defined Content

Web ComponentsCustom Elements

Use a <template> element to clone DOM, instead of setting shadowRoot.innerHTML.

This technique cuts down on HTML parse costs because the content of the template is only parsed once, whereas calling innerHTML on the shadowRoot will parse the HTML for each instance❗️

// ⭐️ content of <template> is only parsed once❗️
let tmpl = document.createElement('template');

tmpl.innerHTML = `
  <style>:host { ... }</style>
  <b>I'm in shadow dom!</b>
  <slot></slot>
`;

customElements.define('custom-element', class extends HTMLElement {

  constructor() {
  
    // always call super() first in the constructor.
    super(); 

    // Attach a shadow root to the element.
    let root = this.attachShadow({mode: 'open'});
    // ⭐️ clone <template> content
    root.appendChild(tmpl.content.cloneNode(true));
  }
  
});

import <template>

🤔 下面的程式碼該如何實作呢?(有空再研究)

<!-- ⭐️ imported from another HTML file -->
<template id="my-element-template">
  <style>
    p { color: green; }
  </style>
  <p>I'm in Shadow DOM. My markup was stamped from a &lt;template&gt;.</p>
</template>

<script>

  // ⭐️ code is inside of an HTML Import (這是什麼❓)
  let tmpl = document.currentScript.ownerDocument.querySelector('#my-element-template');

  customElements.define('my-element-template', class extends HTMLElement {
    constructor() {
      super(); // always call super() first in the constructor.
      let root = this.attachShadow({mode: 'open'});
      root.appendChild(tmpl.content.cloneNode(true));
    }
    ...
  });
</script>

Last updated