如何从Shadow DOM (v1)中访问currentScript并获取目标元素
这个问题我之前也碰到过,document.currentScript返回null通常是因为脚本加载时机的问题(比如异步加载、在自定义元素构造函数里调用时机不对),下面给你几个靠谱的解决办法,按场景选就行:
解决方法
1. 如果你在用自定义元素(最推荐的场景)
如果你的Shadow DOM是附着在自定义元素上的,那构造函数里的this就是当前元素实例,直接通过this.shadowRoot就能拿到Shadow DOM的根节点,之后找.target div就很简单了:
class MyCustomElement extends HTMLElement { constructor() { super(); // 附着Shadow DOM const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ` <div class="target">我是目标元素</div> <script src="./your-script.js"></script> `; // 直接在构造函数里获取目标元素 const targetDiv = shadowRoot.querySelector('.target'); console.log(targetDiv); } } customElements.define('my-custom-element', MyCustomElement);
如果脚本是外部的,在脚本里也可以通过document.currentScript?.getRootNode()来拿ShadowRoot,不过更稳妥的是用自定义元素的实例——比如你可以在脚本里通过document.currentScript.ownerElement.getRootNode(),或者如果脚本在Shadow DOM内,document.currentScript.getRootNode()就是ShadowRoot。
2. 非自定义元素场景:利用脚本的getRootNode()
如果你的Shadow DOM是直接附着在普通元素上的,内联脚本可以这么写:
// 假设这个脚本是直接写在Shadow DOM的<script>标签里 const shadowRoot = document.currentScript.getRootNode(); const targetDiv = shadowRoot.querySelector('.target'); console.log(targetDiv);
如果是外部脚本,document.currentScript可能因为加载时机返回null,这时候可以给脚本加个标识,比如id,然后通过选择器找到脚本,再拿它的根节点:
// 外部脚本里的代码 const script = document.getElementById('shadow-script'); const shadowRoot = script.getRootNode(); const targetDiv = shadowRoot.querySelector('.target');
对应的Shadow DOM结构:
<div id="host"></div> <script> const host = document.getElementById('host'); const shadowRoot = host.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ` <div class="target">目标元素</div> <script id="shadow-script" src="./external.js"></script> `; </script>
3. 动态插入脚本时用闭包传递ShadowRoot
如果你是动态创建脚本元素并插入到Shadow DOM里,可以通过闭包把ShadowRoot变量传递给脚本:
const host = document.getElementById('host'); const shadowRoot = host.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = '<div class="target">目标元素</div>'; const script = document.createElement('script'); // 用闭包让脚本能访问到shadowRoot script.textContent = ` const targetDiv = ${shadowRoot}.querySelector('.target'); console.log(targetDiv); `; shadowRoot.appendChild(script);
为什么document.currentScript会返回null?
常见原因包括:
- 脚本是通过
async或defer属性加载的,这时候脚本执行时document.currentScript会是null - 在自定义元素的构造函数里过早调用(不过其实构造函数里如果是内联脚本应该没问题,外部脚本可能因为加载时机晚)
- 脚本是被动态插入且没有同步执行的
内容的提问来源于stack exchange,提问作者blz
相关产品推荐
相关产品推荐

