自定义元素上的 createElement 中断模板

createElement on Custom Element breaks template

我正在创建两个自定义元素,它们都使用 link rel="import" 添加到 index.html。一个是带槽的容器,另一个是可以在槽中放数字的东西。这两个元素每个都有一个带有模板的 HTML 文件和一个将它们定义为自定义元素的 js 文件的 link。 link 自定义元素 class 对我正在使用的 HTML 模板的声明:

class PuzzlePiece extends HTMLElement{

constructor(){
    super();
    console.dir(document.currentScript);
    const t = document.currentScript.ownerDocument.getElementById('piece-puzzle');
    const shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.appendChild(t.content.cloneNode(true));
 }

这个拼图元素和容器正确渲染,当您手动将它们放在 index.html 灯光下时一切正常 dom

<special-puzzle id="grid">
    <puzzle-piece id="hello"></puzzle-piece>
 </special-puzzle>

但是,一旦我尝试在 index.html 中使用 JS 创建并附加拼图:

<script>
    const addToGrid = document.createElement("puzzle-piece");
    document.getElementById("grid").appendChild(addToGrid);
</script>

我在特殊拼图灯中看到一个新的拼图 dom 但它没有占用插槽,没有渲染,并且控制台出现错误:

Uncaught TypeError: Cannot read property 'content' of null at new PuzzlePiece (puzzle-piece.ts:8) at HTMLDocument.createElement (:3:492) at (index):37

据我所知,问题是在使用 document.createElement 时,浏览器正在进入 class 定义,但 document.currentScript.ownerDocument 与仅手动使用 [=31] 时不同=] 标签。我相信因此,组件找不到它的模板。这是我的第一个 Stack Overflow 问题,所以任何 feedback/help 将不胜感激!

感谢出色的@Supersharp 和他们的

解决了

基本上,为了保留正确的 document.currentScript.ownerDocument,我需要在 class 之前在 var 中声明它,然后在 class 中使用该 var。

旧:

class PuzzlePiece extends HTMLElement{
constructor(){
super();
const t = document.currentScript.ownerDocument.getElementById('piece-puzzle');
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(t.content.cloneNode(true));}

新:

var importedDoc = document.currentScript.ownerDocument;
class PuzzlePiece extends HTMLElement{
constructor(){
super();
const t = importedDoc.getElementById('piece-puzzle');
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(t.content.cloneNode(true));}