为何非沙箱化iframe中无法注册父页面的Web Component?
为什么无法在iframe中注册父页面的Web Component?
问题现象
- 在非沙箱化iframe的脚本(类型为"module",暂未确认是否相关)中执行以下代码时:
customElements.define(name, window.top.customElements.get(name)) - 即便父页面仅注册了如下极简Web Component:
customElements.define(name, class extends HTMLElement { constructor() { super(); } }) - 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 - 但如果直接将父页面的类代码复制到iframe中替换
window.top.customElements.get(name),就能正常运行。
原因分析
这是因为每个浏览器上下文(包括iframe)都有独立的window对象和内置构造函数(比如HTMLElement)。父页面的自定义元素类继承自父窗口的HTMLElement,当你在iframe中使用这个类时,构造函数里的super()会创建父窗口上下文的元素实例,而iframe的自定义元素注册表要求元素必须属于当前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>
内容的提问来源于stack exchange,提问作者Elliot E
相关产品推荐
相关产品推荐

