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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16633057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 08:31:48  来源:igfitidea点击:

Is it possible to access Shadow DOM elements through the parent document?

javascripthtmlweb-componentshadow-dom

提问by James Donnelly

This question is more aimed at user-created shadow DOM elements, but for accessibility I'll use the dateinput type for this question:

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

Say for example I have a dateinput on my page. With a couple of bits edited out, the shadow DOM markup for this (using Chrome) looks something like:

比如说,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>

The methods and properties associated with the dateinput do not appear to reference the shadow DOM at all (JSFiddle), so I was wondering how (if at all) can these shadow DOM elements be accessed?

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

采纳答案by CletusW

@int32_t is right in that Shadow DOM, by definition, is a way to fill a node with DOM that you want to hide from external sources (Encapsulation). The point is that you as the component author get to choose exactly which parts will be exposed to outside CSS or JavaScript and which will not.

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

Unfortunately, you cannot create a public JavaScript interface to your Shadow DOM without using another bleeding-edge spec called Custom Elements. If you choose to do that, it's as simple as adding custom public methods to your element's prototype. From these you can access the internals of your Shadow DOM (see the third example here).

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

You can, however, expose hooks for CSS to access the internals of your Shadow DOM without using Custom Elements. There are two ways to do that:

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

  1. Pseudo-elements
  2. CSS Variables
  1. 伪元素
  2. CSS 变量

Pseudo-elements

伪元素

Chrome and Firefox expose certain parts of their Shadow DOM to CSS through special pseudo-elements. Here'syour example of the dateinput with the addition of a CSS rule that only applies to the numerical part of the date field through use of the Chrome-provided -webkit-datetime-editpseudo-element.

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

Here'sa partial list of the available WebKit pseudo-elements. You can also just enable the Show Shadow DOMoption in DevTools and look for attributes named pseudo.

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

Component authors can also create their own pseudo-elements to expose parts of their Shadow DOM (see the 2nd example here).

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

CSS Variables

CSS 变量

An even better way is to use CSS Variables, which you can enable with Enable experimental WebKit featuresin about:flagsin Chrome. Then check out this fiddlewhich uses CSS Variables to communicate to the Shadow DOM what color it should use for its "theme."

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

回答by Supersharp

Now (2016) you can access open user-createdshadow DOM elements (but no user agent-created shadow DOM!) using the method querySelectoron the Shadow DOM root:

现在(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>

//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>

回答by int32_t

You can't access content of Shadow DOM from scripts outside of the Shadow DOM. Encapsulation is the purpose of Shadow DOM.

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

回答by pravchuk

Yes. You just have to call .root or .shadowRoot . Here's an example,

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

document.getElementById('itemId').root 

You will not get the shadow dom element without the innerText or innerHTML on the parent dom element.

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