查询#shadow-root内部的元素由于元素选择域不同查询的结果不同?

查询#shadow-root内部的元素是发生了奇怪的问题

document.querySelector("#marketplace > div.css-6t2hm5 > div > div > div.css-p8gz4h > div.css-wr75lm > div > div.css-9vd5ud > div > div.css-1yhwvbb > div:nth-child(3)")

document.querySelector("#app > div.r6s-marketplace.undefined > div > div > ubisoft-connect")

分别是#shadow-root内外的两个元素通过F12在元素页面右键复制JS路径获得,当我在元素页面点击#shadow-root外部的元素代码时,可以查询#shadow-root外的元素,查询内部元素为null,当我在元素页面点击#shadow-root内部的元素代码时,可以查询#shadow-root内的元素,查询外部元素为null,默认是只能查询#shadow-root外的元素,请问下怎样在不打开F12在元素页面点击#shadow-root内部的元素代码却能够查询#shadow-root内的元素


使用间接的获取到挂载的 shadowRoot 之后再去查询内部的元素我也试过,但是shadowRoot获取能打印出来,里面的iframe和style都能打印,但一旦使用这个元素进行查询却都为null

阅读 1.3k
avatarAI BotBETA

在 Web Components 的 Shadow DOM 中,元素的查询确实与常规的 DOM 查询有所不同。Shadow DOM 提供了一种封装内部 DOM 结构的方式,使得从外部无法直接通过常规的选择器访问 Shadow DOM 内部的元素。这是为了提供组件化开发的封装性和独立性。

对于你提出的问题,要在不打开开发者工具(F12)的情况下,从外部查询 Shadow DOM 内部的元素,你通常需要通过组件提供的公共接口或者方法来实现。Shadow DOM 的设计初衷就是阻止外部直接访问其内部元素,因此,没有直接的方法可以通过选择器从外部穿透 Shadow DOM 边界。

不过,有几种可能的方法可以尝试:

  1. 使用组件提供的 API:如果组件开发者提供了访问 Shadow DOM 内部元素的 API 或方法,你可以通过这些 API 或方法获取到内部元素。这通常是在组件设计时就已经考虑到的,是最佳实践。
  2. 遍历 Shadow Root:如果你有对 Shadow Host 的引用,并且想要访问其 Shadow DOM,你可以通过 shadowRoot 属性来访问它,然后在里面使用查询方法。例如:

    const shadowHost = document.querySelector('#shadow-host-element');
    if (shadowHost.shadowRoot) {
        const elementInsideShadow = shadowHost.shadowRoot.querySelector('你的选择器');
        // 现在你可以操作 elementInsideShadow 了
    }
  3. 使用全局事件监听:如果你只是想在 Shadow DOM 内部元素上监听事件,你可以从外部添加事件监听器,并在 Shadow DOM 内部触发自定义事件。这样,即使你不能直接访问内部元素,也可以通过事件交互。
  4. 修改组件:如果你有能力并且需要修改组件的源代码,你可以考虑修改组件以暴露更多功能或接口,但这通常不是推荐的做法,因为它违反了组件封装的原则。

总之,由于 Shadow DOM 的设计特性,从外部直接查询其内部元素通常是不被允许的。最佳的做法是通过组件提供的接口和方法来与 Shadow DOM 内部的元素进行交互。如果你没有这些接口和方法的访问权限,那么你可能需要重新考虑你的设计或者与组件的开发者进行沟通。

1 个回答

改一下查询的方式,如果要查询 shadowRoot 内部的元素,把 document.querySelector 改动一下,使用 Element.shadowRoot 获取到挂载的 shadowRoot 之后再去查询内部的元素,比如说:

let shadowRoot = document.querySelector("ubisoft-connect").shadowRoot;
let element = shadowRoot.querySelector(对应的选择器);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题