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

时间:2013-05-19 09:10:51

标签: javascript html5 web-component shadow-dom

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

比如说我的页面上有date输入。在编辑了几个位之后,这个(使用Chrome)的阴影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 个答案:

答案 0 :(得分:18)

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

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

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

  1. 伪元素
  2. CSS变量
  3. 伪元素

    Chrome和Firefox通过特殊的伪元素将其Shadow DOM的某些部分暴露给CSS。 Here'sdate输入的示例,其中添加了一条CSS规则,该规则仅适用于日期字段的数字部分,方法是使用Chrome提供的-webkit-datetime-edit伪元素。 / p>

    Here's可用的WebKit伪元素的部分列表。您也可以在DevTools中启用Show Shadow DOM选项,并查找名为pseudo的属性。

    组件作者也可以创建自己的伪元素来公开他们的Shadow DOM部分(参见第二个例子here)。

    CSS变量

    更好的方法是使用CSS变量,您可以在Chrome中的Enable experimental WebKit features中使用about:flags启用它。然后查看使用CSS变量的this fiddle与Shadow DOM进行通信,了解它应该用于“主题”的颜色。

答案 1 :(得分:15)

现在(2016)您可以使用Shadow DOM根目录上的方法querySelector访问开放的用户创建的影子DOM元素(但没有用户代理创建的影子DOM!): / p>

<body>
    <div id="container"></div>
    <script>
        //Shadow Root
        var root = container.createShadowRoot()
        //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>

//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 )
}
<!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>

答案 2 :(得分:4)

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

答案 3 :(得分:1)

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

document.getElementById('itemId').root 

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