【问题标题】:Failed to construct 'CustomElement': The result must not have a parent未能构造“CustomElement”:结果不能有父级
【发布时间】:2020-04-21 06:25:35
【问题描述】:

我正在使用 Web Components 创建自定义 HTML 元素

我通过 REST 服务检索一些 JSON 数据,并希望根据响应动态创建自定义元素。

class LibraryFolders extends HTMLElement {
    async connectedCallback() {
        // Load folders
        const foldersResponse = await fetch('/wp-json/prodes-media-library/v1/folders');
        const foldersResponseJson = await foldersResponse.json();

        foldersResponseJson.forEach(folder => {
            document.createElement('library-folder');
        });
    }
}

customElements.define('library-folders', LibraryFolders);

这可以正常工作,当使用 createElement 创建元素时,它会在名为 LibraryFolder 的 customElement 类中调用 constructor

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

        // logs <library-folder></library-folder>
        console.log(this);

        // This results eventually into the following error:
        // Failed to construct 'CustomElement': The result must not have a parent
        document.querySelector('#folders').appendChild(this);
    }
}

customElements.define('library-folder', LibraryFolder);

我尝试归档的是在class LibraryFolder 中的constructor 被触发后追加 library-folder 元素到名为&lt;div id="folders"&gt;&lt;/div&gt; 的元素。

但是,当尝试这样做会导致以下错误:

未捕获的 DOMException:构造“CustomElement”失败:结果不能有父对象
在 HTMLDocument.createElement (:1:1536)
在 HTMLDocument.document.createElement (:292:44)
在(网址)
在 Array.forEach ()
在 HTMLElement.connectedCallback (URL)

我在这里做错了什么?与其他类似错误不同,文档中没有关于此错误的信息。

【问题讨论】:

  • 也许它告诉您组件需要在创建之后添加到DOM。该异常来自createElement 内部,表明它会检查您的构造函数创建的对象以验证它是否还不是 DOM 的一部分,如果您考虑一下 createElement 的返回值不应该是这种情况.
  • @Pointy 所以我不应该将它添加到构造函数内的 DOM 中?
  • 对。想一想:createElement() 在正常情况下的概念是制作一个新元素,以后可以在某个地方添加或不添加到 DOM 中。将自身添加到 DOM 的元素会很奇怪。 (一方面,它不能独立于特定的页面结构工作。)
  • @Pointy 是的,An element that adds itself to the DOM would be weird 这听起来很合乎逻辑。让我试试看,然后再回来看看它是否有效。
  • @Pointy 谢谢你,你把我送到了正确的方向,我设法用你的 cmets 解决了它。我已将其添加为将来遇到相同错误的人的答案。

标签: javascript es6-class custom-element


【解决方案1】:

感谢@pointy 让我走向正确的方向。

将自身添加到 DOM 的元素会很奇怪。 (一方面, 它不能独立于特定的页面结构工作。)


问题是我试图使用自己的constructor元素 添加到 DOM,我还发现如果你设法让它工作在constructor 中,它将导致。

超过最大调用堆栈大小。

我设法通过在类中创建一个函数来解决这个问题,该函数可以稍后调用以将 element 附加到 DOM

class LibraryFolder extends HTMLElement {
    constructor() {
        super();
    }

    appendToDom() {
        // Moved this outside the constructor
        document.querySelector('#folders').appendChild(this);;
    }
}

customElements.define('library-folder', LibraryFolder);

然后在LibraryFolders 类中调用该函数。

class LibraryFolders extends HTMLElement {
    async connectedCallback() {
        // Load folders
        const foldersResponse = await fetch('/wp-json/prodes-media-library/v1/folders');
        const foldersResponseJson = await foldersResponse.json();

        foldersResponseJson.forEach(folder => {
            const node = document.createElement('library-folder');

            // Now it works correctly :)
            node.appendToDom();
        });
    }
}

customElements.define('library-folders', LibraryFolders);

补充一下,根据规范,这个错误是正确的。 If result’s parent is not null, then throw a "NotSupportedError" DOMException.

Chrome 没有给出正确的错误,但是如果你在 Firefox 中尝试,你会得到指定的错误

更多详情请查看 https://dom.spec.whatwg.org/#dom-document-createelement

【讨论】:

  • 没试过但不应该this.append(...folderResponseJson.map(f=&gt;document.createElement('library-folder'))对性能和解耦更好
猜你喜欢
  • 1970-01-01
  • 2019-10-10
  • 2017-07-25
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 2018-04-21
  • 1970-01-01
相关资源
最近更新 更多