是否可以通过父文档访问 Shadow DOM 元素?

IT技术 javascript html web-component shadow-dom
2021-02-07 16:32:54

这个问题更多地针对用户创建的 shadow DOM 元素,但为了可访问性,我将使用date输入类型来解决这个问题:

例如,说date我的页面上有一个输入。编辑掉一些位后,这个(使用 Chrome)的 shadow DOM 标记看起来像:

<input type="date">
    #document-fragment
        <div pseudo="-webkit-datetime-edit">
            <div pseudo="-webkit-datetime-edit-fields-wrapper">
                <span role="spinbutton">dd</span>
                <div pseudo="-webkit-datetime-edit-text">/</div>
                <span role="spinbutton">mm</span>
                <div pseudo="-webkit-datetime-edit-text">/</div>
                <span role="spinbutton">yyyy</span>
            </div>
        </div>
        <div></div>
        <div pseudo="-webkit-calendar-picker-indicator"></div>

date输入相关的方法和属性似乎根本没有引用影子 DOM ( JSFiddle ),所以我想知道如何(如果有的话)可以访问这些影子 DOM 元素?

4个回答

@int32_t 是正确的,根据定义,Shadow DOM 是一种用想要从外部源(封装隐藏的 DOM 填充节点的方法关键是您作为组件作者可以准确选择哪些部分将暴露给外部 CSS 或 JavaScript,哪些不会。

不幸的是,如果不使用另一个名为Custom Elements的前沿规范,就无法为 Shadow DOM 创建公共 JavaScript 接口如果您选择这样做,就像将自定义公共方法添加到元素的原型一样简单。通过这些,您可以访问 Shadow DOM 的内部结构(请参阅此处的第三个示例)。

但是,您可以为 CSS 公开挂钩以访问 Shadow DOM 的内部结构,而无需使用自定义元素。有两种方法可以做到这一点:

  1. 伪元素
  2. CSS 变量

伪元素

Chrome 和 Firefox 通过特殊的伪元素将它们 Shadow DOM 的某些部分暴露给 CSS。这是date添加了 CSS 规则输入示例,该规则仅通过使用 Chrome 提供的-webkit-datetime-edit伪元素应用于日期字段的数字部分

这是可用的 WebKit 伪元素的部分列表。您也可以只Show Shadow DOM在 DevTools 中启用该选项并查找名为pseudo.

组件作者还可以创建他们自己的伪元素来公开他们的 Shadow DOM 的一部分(请参阅此处的第二个示例)。

CSS 变量

一个更好的方法是使用CSS变量,你可以启用Enable experimental WebKit featuresabout:flagsChrome浏览器。然后查看这个使用 CSS 变量与 Shadow DOM 通信的小提琴,它应该为“主题”使用什么颜色。

上面提供的一个更新的小提琴:jsfiddle.net/r3httdhs
2021-03-19 16:32:54
如果没有一些技巧,您就不能从 Javascript 访问 Shadow DOM,这是有道理的。但是有没有办法在那里运行 Javascript?
2021-03-29 16:32:54
我喜欢这个答案......但是,有一个关于最后一部分的问题评论,它揭示了使用 CSS 变量的答案或方向......这假设用户已经在其作用域 shadow-dom 内提供了一个样式表。如果他们没有呢?例如,如果他们只是设置样式而不提供变量会怎样。如何在没有 css 变量和/或伪元素的情况下访问 SD 中的类?顺便说一下,你所拥有的 jsfiddle 似乎已经被弃用了
2021-04-01 16:32:54
就vanilla Shadow DOM 而言,我不是最适合提问的人,但是当您使用自定义元素时,您当然可以。例如,查看Polymer
2021-04-13 16:32:54

现在(2016 年)您可以使用Shadow DOM 根上的方法访问开放的用户创建的shadow DOM 元素(但没有用户代理创建的 shadow DOM!)querySelector

<body>
    <div id="container"></div>
    <script>
        //Shadow Root
        ̶v̶a̶r̶ ̶r̶o̶o̶t̶ ̶=̶ ̶c̶o̶n̶t̶a̶i̶n̶e̶r̶.̶c̶r̶e̶a̶t̶e̶S̶h̶a̶d̶o̶w̶R̶o̶o̶t̶(̶)̶
        //new syntax:
        var root = container.attachShadow( { mode: "open" } )

        //Inside element
        var span = document.createElement( "span" )
        span.textContent = "i'm inside the Shadow DOM"
        span.id = "inside"
        root.appendChild( span )

        //Access inside element
        console.log( container.shadowRoot.querySelector( "#inside" ) )
    </script>
</body>

为什么我们仍然不能访问用户代理影子 dom?
2021-03-23 16:32:54
createShadowRoot()方法,取而代之的被弃用attachShadow()
2021-03-28 16:32:54
那么有没有办法在那种输入编辑器中获取文本?
2021-04-04 16:32:54
我想这是因为它是本机浏览器实现,而不是真正的 html。
2021-04-08 16:32:54

您无法从 Shadow DOM 之外的脚本访问 Shadow DOM 的内容。封装是 Shadow DOM 的目的。

是的。你只需要调用 .root 或 .shadowRoot 。这是一个例子,

document.getElementById('itemId').root 

如果父 dom 元素上没有 innerText 或 innerHTML,您将无法获得 shadow dom 元素。