如何从Shadow DOM内的script标签获取shadowRoot?
无需显式定位宿主元素,直接在Shadow DOM内部获取shadowRoot
问题背景
目前在Shadow DOM中注入脚本时,需要先通过document定位宿主元素,再获取shadowRoot来查找目标元素,例如:
var selector = "document.querySelector('#shadow').shadowRoot.querySelector('img')";
想知道是否可以无需显式指定宿主元素,直接从Shadow DOM内部的脚本中获取对应的shadowRoot?尝试过document.currentScript但在Shadow DOM中返回null。
示例代码
JavaScript代码
document.querySelector('#shadow').attachShadow({mode: 'open'}); var shadow = document.querySelector('#shadow'); shadow.shadowRoot.innerHTML = '<img id="img"><div></div>'; var scriptElement = document.createElement('script'); // 希望这里能使用相对选择器,不依赖宿主元素ID var selector = "document.querySelector('#shadow').shadowRoot.querySelector('img')"; scriptElement.textContent = ` JsBarcode(${selector}, "401246", { format: "CODE128", displayValue: true, height: 25, width: 1, fontSize: 16, lineColor: "#000000" } ); `; var shadowDiv = document.querySelector('#shadow').shadowRoot.querySelector('div'); shadowDiv.appendChild(scriptElement);
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="src/style.css"> </head> <body> <h1 id="header"></h1> <div id="shadow"></div> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsbarcode/3.11.5/JsBarcode.all.min.js"></script> <script src="src/script.js"></script> </body> </html>
解决方案
document.currentScript在动态注入到Shadow DOM的脚本中确实容易返回null,可以用以下两种相对定位的方法:
方法1:利用脚本元素的getRootNode()获取shadowRoot
脚本执行时,顶层的this指向当前脚本元素(非严格模式下),通过this.getRootNode()可以直接获取所在的Shadow Root,无需依赖宿主元素ID:
scriptElement.textContent = ` JsBarcode(this.getRootNode().querySelector('#img'), "401246", { format: "CODE128", displayValue: true, height: 25, width: 1, fontSize: 16, lineColor: "#000000" } ); `;
这种方式完全基于脚本自身的位置进行相对查找,不需要硬编码宿主元素的选择器。
方法2:注入脚本时传递shadowRoot引用
如果需要更直接的方式,可以在创建脚本时,直接把已有的shadowRoot引用传递进去:
scriptElement.textContent = ` const shadowRoot = ${shadow.shadowRoot}; JsBarcode(shadowRoot.querySelector('#img'), "401246", { format: "CODE128", displayValue: true, height: 25, width: 1, fontSize: 16, lineColor: "#000000" } ); `;
这种方式依赖外部的shadow变量,但不需要在脚本内部查找宿主元素。
说明
document.currentScript失效的原因是:动态创建并插入的脚本元素,在执行时可能已经脱离了"当前脚本"的上下文,尤其是在Shadow DOM环境中,浏览器的currentScript指向可能不会正确绑定到注入的脚本上。而this.getRootNode()是从当前脚本元素出发,直接获取其所在的根节点(即Shadow Root),更可靠。
内容的提问来源于stack exchange,提问作者Ash McConnell
相关产品推荐
相关产品推荐

