为什么将自定义 HTML 元素放入另一个元素中会导致第二个元素被隐藏?

问题描述 投票:0回答:1

TL;DR:当一个自定义元素位于另一个自定义元素内部时,第二个元素将无法渲染。这是为什么?如何解决?

说明

我使用 JS 创建了三个自定义 HTML 元素和两个

template
(如下所示)。

const baseTemplate = document.createElement("template");
baseTemplate.innerHTML = `
<slot name="left-pane">Warning: left-pane not included</slot>
<slot name="right-pane">Warning: right-pane not included</slot>
`;

const paneTemplate = document.createElement("template");
paneTemplate.innerHTML = `<slot name="content">Warning: no content included</slot>`;

class PageBase extends HTMLElement {
    constructor() {
        super();

        const shadow = this.attachShadow({ mode: "closed" });

        let clone = baseTemplate.content.cloneNode(true);
        shadow.append(clone);
    }
}

class LeftPane extends HTMLElement {
    constructor() {
        super();

        const shadow = this.attachShadow({ mode: "closed" });

        let clone = paneTemplate.cloneNode(true);
        shadow.append(clone);
    }
}

class RightPane extends HTMLElement {
    constructor() {
        super();

        const shadow = this.attachShadow({ mode: "closed" });

        let clone = paneTemplate.cloneNode(true);
        shadow.append(clone);
    }
}

customElements.define("page-base", PageBase);
customElements.define("left-pane", LeftPane);
customElements.define("right-pane", RightPane);

在 HTML 文档中(如下所示),当

right-pane
left-pane
放入另一个自定义元素(在本例中为
page-base
)中时,它不会在浏览器中呈现。

<!DOCTYPE html>
<html lang="en">

<head>
    [...]
    <script src="js/layout.js" type="module"></script>   <!---This is the JS file seen above--->
</head>

<body>
    <page-base>
        <div slot="left-pane">
            <p>Thing 1</p>
        </div>
        <div slot="right-pane">
            <right-pane>
                <p slot="content">Thing 3</p>
            </right-pane>
            <p>Thing 2</p>
        </div>
    </page-base>
</body>

</html>

问题:渲染

Thing 1
Thing 2
,但不渲染
Thing 3
。这是为什么?我该如何解决?

我尝试过单独使用每个自定义元素,它们可以很好地将标题或段落标签放入其中,但不适用于自定义元素。

javascript html css
1个回答
0
投票

我认为“Thing 3”没有出现的原因是模板的克隆方式。具体来说,在

paneTemplate
LeftPane
类中克隆
RightPane
时,您使用的是
paneTemplate.cloneNode(true)
而不是
paneTemplate.content.cloneNode(true)
。这会导致一个空的影子 DOM,因为模板本身的
cloneNode
方法不包含其内容。

const baseTemplate = document.createElement("template")
baseTemplate.innerHTML = `
<slot name="left-pane">Warning: left-pane not included</slot>
<slot name="right-pane">Warning: right-pane not included</slot>
`

const paneTemplate = document.createElement("template")
paneTemplate.innerHTML = `<slot name="content">Warning: no content included</slot>`

class PageBase extends HTMLElement {
  constructor() {
    super()

    const shadow = this.attachShadow({
      mode: "closed"
    })

    let clone = baseTemplate.content.cloneNode(true)
    shadow.append(clone)
  }
}

class LeftPane extends HTMLElement {
  constructor() {
    super()

    const shadow = this.attachShadow({
      mode: "closed"
    })

    let clone = paneTemplate.content.cloneNode(true)
    shadow.append(clone)
  }
}

class RightPane extends HTMLElement {
  constructor() {
    super()

    const shadow = this.attachShadow({
      mode: "closed"
    })

    let clone = paneTemplate.content.cloneNode(true)
    shadow.append(clone)
  }
}

customElements.define("page-base", PageBase)
customElements.define("left-pane", LeftPane)
customElements.define("right-pane", RightPane)
<!doctype html>
<html lang="en">

<head> </head>

<body>
  <page-base>
    <div slot="left-pane">
      <p>Thing 1</p>
    </div>
    <div slot="right-pane">
      <right-pane>
        <p slot="content">Thing 3</p>
      </right-pane>
      <p>Thing 2</p>
    </div>
  </page-base>
</body>

</html>

© www.soinside.com 2019 - 2024. All rights reserved.