为什么在未进行沙箱限制的iframe中,父页面注册的Web组件会不起作用?

前端开发 2026-07-08

当在一个(未沙箱)iframe的脚本中调用 customElements.define(name, window.top.customElements.get(name)) 时(若这有实际意义,这里以type="module" 为前提),在Chrome中总是会抛出错误 Uncaught TypeError: custom element constructors must call super() first and must not return a different object,在Firefox中则是 Uncaught TypeError: Custom element constructor returned a wrong element,即使这是一个在顶层注册的极其简单的Web组件,例如:

customElements.define(name, class extends HTMLElement {
  constructor() {
    super();
  }
})

但如果我把那个类直接替换到 window.top.customElements.get(name) 的位置,那么就能工作。

是否有某些原因,父页面注册的Web组件在iframe中不可用?

下面给出一个完整的、最小可复现的示例(注意,这个示例在像codepen这样的工具中使用iframe来运行代码时将不起作用,因为那会改变 window.top 的含义。这个示例需要放在一个HTML文件中来试用):

<script type="module">
  customElements.define(
    "my-el",
    class extends HTMLElement {
      constructor() {
        super();
      }
    }
  );
</script>

<iframe
  srcdoc="
  <my-el></my-el>
  <script>
    customElements.define('my-el', window.top.customElements.get('my-el'))
  </script>"
>
</iframe>

回答后的补充:另请参阅:How we can copy custom elements from parent window inside iframe window? 该文中有关于该领域新网页标准的回答,以及如何在顶层页面和iframe中对定义自定义组件的文件直接使用import的做法。不过该文并未回答为何不能在iframe中注册在顶层页面定义的Web组件,这篇才有。

解决方案

仅回答原因:

js class extends HTMLElement { 中被引用的 HTMLElement 接口来自顶层上下文,而不是来自iframe自身的接口。当iframe的文档尝试使用它来生成一个元素时,它会发现它并不是自身返回的 HTMLElement 的一个实例,因此会抛出。

这等同于直接对 class extends window.top.HTMLElement 进行操作,结果同样会失败:https://jsfiddle.net/f7dr23ew/1(因为StackSnippet的 iframe没有原点,无法运行该演示)。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章