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
。这是为什么?我该如何解决?
我尝试过单独使用每个自定义元素,它们可以很好地将标题或段落标签放入其中,但不适用于自定义元素。
我认为“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>