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

Jam*_*lly 29 javascript html5 web-component shadow-dom

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

比方说,date我的页面上有一个输入.编辑完几个位后,阴影DOM标记(使用Chrome)看起来像:

<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>
Run Code Online (Sandbox Code Playgroud)

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

Cle*_*usW 18

date根据定义,Shadow DOM是一种用DOM填充节点的方法,你想要从外部源中隐藏(Encapsulation).关键是你作为组件的作者可以准确地选择哪些部分将暴露给外部CSS或JavaScript,哪些不会.

遗憾的是,如果不使用另一个名为Custom Elements的前沿规范,则无法为Shadow DOM创建公共JavaScript界面.如果您选择这样做,就像向元素的原型添加自定义公共方法一样简单.从这些中,您可以访问Shadow DOM的内部(请参阅此处的第三个示例).

但是,您可以为CSS公开挂钩,以便在不使用自定义元素的情况下访问Shadow DOM的内部.有两种方法可以做到这一点:

  1. 伪元素
  2. CSS变量

伪元素

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

这是可用的WebKit伪元素的部分列表.您也pseudo可以在DevTools中启用该选项并查找名为的属性Enable experimental WebKit features.

组件作者还可以创建自己的伪元素以暴露其Shadow DOM的部分(请参阅此处的第2个示例).

CSS变量

一个更好的方法是使用CSS变量,你可以启用about:flagsdateChrome浏览器.然后看看这个小提琴,它使用CSS变量向Shadow DOM传达它应该用于"主题"的颜色.

  • 上面提供的小提琴的更新:http://jsfiddle.net/r3httdhs/ (2认同)

Sup*_*arp 17

现在(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>
Run Code Online (Sandbox Code Playgroud)

//Shadow Root
var root = container.createShadowRoot()

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

//Access inside element
function get() 
{
  alert( container.shadowRoot.querySelector( "#inside" ).id )
}
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>
<head>
    <title></title>
	<meta charset="utf-8" />
</head>
<body>
	<div id="container"></div>
    <button onclick="get()">Get</button>
	<script>
	</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)


pra*_*huk 7

是的。您只需调用 .root 或 .shadowRoot 即可。这是一个例子,

document.getElementById('itemId').root 
Run Code Online (Sandbox Code Playgroud)

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