<template/>和Shadow Dom一起使用时为什么需要使用cloneNode 没有 cloneNode 的代码使用 cloneNode 的代码

问题描述

我一直在查看有关 Web 组件的 mdn 文档,我点击了链接,然后我到达了有关模板下方的文档,该链接就是我正在查找的内容

根据文件

mdn sceenshot

它说如果我不使用 cloneNode 附加节点?模板的内部样式将不起作用。但是我尝试使用 cloneNode 追加和追加,但两个测试都是相同的....所以我有一个问题,我是否想念理解或规范更改以支持两者?我在 chrome 、 safari 中测试了两个浏览器

没有 cloneNode 的代码

<template id="my-paragraph">
    <style>
      p {
        color: white;
        background-color: #666;
        padding: 5px;
      }
    </style>
    <p>My paragraph</p>
  </template>
<my-paragraph></my-paragraph>

<script>
  customElements.define('my-paragraph',class extends HTMLElement {
      constructor() {
        super();
        let template = document.getElementById('my-paragraph');
        let templateContent = template.content;
        const shadowRoot = this.attachShadow({
          mode: 'open'
        })
        var style = document.createElement('style');
        style.textContent = `
p{
  font-size: 30px;
  color:'black';
}`;
        shadowRoot.appendChild(style)
        console.log(template)
        shadowRoot.appendChild(templateContent);
      }
    }
  );
</script>

使用 cloneNode 的代码

<template id="my-paragraph">
    <style>
      p {
        color: white;
        background-color: #666;
        padding: 5px;
      }
    </style>
    <p>My paragraph</p>
  </template>
<my-paragraph></my-paragraph>

<script>
  customElements.define('my-paragraph',class extends HTMLElement {
      constructor() {
        super();
        let template = document.getElementById('my-paragraph');
        let templateContent = template.content;
        const shadowRoot = this.attachShadow({
          mode: 'open'
        })
        var style = document.createElement('style');
        style.textContent = `
p{
  font-size: 30px;
  color:'black';
}`;
        shadowRoot.appendChild(style)
        console.log(template)
        shadowRoot.appendChild(templateContent.cloneNode(true));
      }
    }
  );
</script>

https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots

解决方法

.content 移动内容,
.content.cloneNode(true)<template>

进行深层复制

请参阅下面的 SO 片段; 3rd <my-paragraph> 无法从 <template> 获取任何内容,因为 2nd <my-paragraph> 移动了所有模板到其 <my-paragraph> shadowDOM

<template id="MY-PARAGRAPH">
    <style>
      p {
        background: lightgreen;
        padding: 5px;
      }
    </style>
    <p><slot></slot></p>
  </template>
<my-paragraph cloned>Cloned Content</my-paragraph>
<my-paragraph>Content only</my-paragraph>
<my-paragraph>Content only</my-paragraph>
<script>
  customElements.define('my-paragraph',class extends HTMLElement {
      constructor() {
        // yes you can place javascript BEFORE the super() call,the docs are wrong
        const template = () => {
          let content = document.getElementById(this.nodeName).content;
          if (content.children.length) {
            if (this.hasAttribute("cloned"))
              return content.cloneNode(true)
            else
              return content;
          } else {
            document.body.append(`content in template: `,this.nodeName);
          }
        }
        super() // sets AND returns this-Scope
          .attachShadow({mode: 'open'})  // sets AND returns this.shadowRoot
          .append(template()) // no need for appendChild if you don't use its return value
      }
    }
  );
</script>