Chrome扩展content script调用customElements.define报错问题咨询
错误原因
- 执行时机过早:如果你的content script配置了
run_at: document_start,此时页面DOM还未完成初始化,window.customElements接口还未挂载到window对象上,访问时返回null,调用define方法就会抛出该错误。 - 隔离环境限制:Chrome扩展的content script运行在独立的隔离世界中,部分低版本Chrome不会向隔离世界暴露
window.customElements接口,直接访问就会得到null。
解决方案
方案1:调整content script执行时机
修改manifest.json中content script的执行时机配置,将run_at设置为document_idle或document_end,确保页面基础接口初始化完成后再执行代码:
{ "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_idle" } ] }
方案2:增加接口存在判断
如果需要提前执行代码,可以添加轮询判断,等window.customElements可用后再执行注册逻辑:
function tryRegister() { if (!window.customElements) { setTimeout(tryRegister, 30); return; } class MyWebComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.shadowRoot.innerHTML = ` <p>I'm in the Shadow Root!</p> `; } } window.customElements.define("my-web-component", MyWebComponent); } tryRegister();
方案3:将注册逻辑注入主世界执行
页面主世界的window.customElements接口是完整可用的,你可以通过创建script标签的方式把自定义元素注册逻辑注入到主世界执行:
const injectScript = document.createElement('script'); injectScript.textContent = ` class MyWebComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.shadowRoot.innerHTML = \` <p>I'm in the Shadow Root!</p> \`; } } window.customElements.define("my-web-component", MyWebComponent); `; document.documentElement.appendChild(injectScript); injectScript.remove();
内容的提问来源于stack exchange,提问作者user17085802
相关产品推荐
相关产品推荐

