You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:01:12