[英]How to get element in user-agent shadow root with JavaScript?
I need get elements from Shadow DOM and change it.我需要从 Shadow DOM 中获取元素并对其进行更改。 How i can do it?
我该怎么做?
<div>
<input type="range" min="100 $" max="3000 $">
</div>
You cannot access a Shadow DOM created by the browser to display a control, that is called a #shadow-root (user-agent)
in the Dev Tools.您无法访问由浏览器创建的 Shadow DOM 来显示控件,在开发工具中称为
#shadow-root (user-agent)
。 <input>
is one example. <input>
就是一个例子。
You can only access open custom Shadow DOM (the ones that you create yourself), with the { mode: 'open' }
option.您只能使用
{ mode: 'open' }
选项访问打开的自定义 Shadow DOM(您自己创建的)。
element.attachShadow( { mode: 'open' } )
Update更新
It's true for most UX standard HTML elements: <input>
, <video>
, <textarea>
, <select>
, <audio>
, etc.大多数 UX 标准 HTML 元素都是如此:
<input>
、 <video>
、 <textarea>
、 <select>
、 <audio>
等。
3rd party edit 2022第 3 方编辑 2022
The following might help to illustrate the question.以下内容可能有助于说明问题。 Give there is only 1
<input type=range>
in the html document this code shows if its children can be accessed.假设 html 文档中只有 1 个
<input type=range>
,这段代码显示了它的子项是否可以被访问。
// returns 1 as expected since only one input element is in the document
document.querySelectorAll("input").length;
// get a reference to <input type=range>
var rangeInput = document.querySelector("input");
// Is it a shadowRoot?
// if null then either
// - it is not a shadowRoot OR
// - its elements can not be accessed (mode == closed)
console.log(rangeInput.shadowRoot); // returns null
The code above shows that the internals of an <input type=range>
can not be accessed.上面的代码表明
<input type=range>
的内部不能被访问。
Here is an example:这是一个例子:
var container = document.querySelector('#example');
//Create shadow root !
var root = container.createShadowRoot();
root.innerHTML = '<div>Root<div class="test">Element in shadow</div></div>';
//Access the element inside the shadow !
//"container.shadowRoot" represents the youngest shadow root that is hosted on the element !
console.log(container.shadowRoot.querySelector(".test").innerHTML);
Demo:演示:
var container = document.querySelector('#example'); //Create shadow root ! var root = container.createShadowRoot(); root.innerHTML = '<div>Root<div class="test">Element in shadow</div></div>'; //Access the element inside the shadow ! console.log(container.shadowRoot.querySelector(".test").innerHTML);
<div id="example">Element</div>
I hope this will help you.我希望这能帮到您。
To answer (a generalized version of) the OP question:要回答(广义版本)OP 问题:
It feels like the shadow root API is still lacking (or I just don't know it well enough).感觉好像仍然缺少影子根 API(或者我只是不太了解它)。 But it basically renders
querySelectorAll
somewhat useless, in that querySelectorAll
will not actually get all matching elements anymore, since it simply ignores all ancestors in shadowRoots
.但它基本上使
querySelectorAll
有点无用,因为querySelectorAll
实际上不会再获得所有匹配的元素,因为它只是忽略了shadowRoots
中的所有祖先。 Maybe there is an API that fixes that, but just in case there is not:也许有一个 API 可以解决这个问题,但以防万一:
Here is a simple function that recursively iterates all shadowRoots
and gets you all matching elements on the page, not just those of a single shadowRoot
.这是一个简单的函数,它递归地迭代所有
shadowRoots
并获取页面上所有匹配的元素,而不仅仅是单个shadowRoot
的元素。
/**
* Finds all elements in the entire page matching `selector`, even if they are in shadowRoots.
* Just like `querySelectorAll`, but automatically expand on all child `shadowRoot` elements.
* @see https://stackoverflow.com/a/71692555/2228771
*/
function querySelectorAllShadows(selector, el = document.body) {
// recurse on childShadows
const childShadows = Array.from(el.querySelectorAll('*')).
map(el => el.shadowRoot).filter(Boolean);
// console.log('[querySelectorAllShadows]', selector, el, `(${childShadows.length} shadowRoots)`);
const childResults = childShadows.map(child => querySelectorAllShadows(selector, child));
// fuse all results into singular, flat array
const result = Array.from(el.querySelectorAll(selector));
return result.concat(childResults).flat();
}
// examples:
querySelectorAllShadows('td'); // all `td`s in body
querySelectorAllShadows('.btn') // all `.btn`s in body
querySelectorAllShadows('a', document.querySelector('#right-nav')); // all `a`s in right menu
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.