How to get element in user-agent shadow root with JavaScript?

问题描述 投票:0回答:3

我需要从 Shadow DOM 获取元素并更改它。我该怎么做?

<div>
     <input type="range" min="100 $" max="3000 $">
</div>
javascript html web-component shadow-dom
3个回答
33
投票

您不能访问由浏览器创建的 Shadow DOM 来显示控件,这在开发工具中称为

#shadow-root (user-agent)
<input>
就是一个例子。

您只能使用 { mode: 'open' } 选项访问

open
自定义 Shadow DOM(您自己创建的)。

element.attachShadow( { mode: 'open' } )

更新

对于大多数 UX 标准 HTML 元素都是如此:

<input>
<video>
<textarea>
<select>
<audio>

第三方编辑 2022

以下可能有助于说明问题。在 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

上面的代码显示无法访问

<input type=range>
的内部。


12
投票

回答 OP 问题的通用版本:

从页面上的任何地方查询阴影元素?

感觉还是缺少shadow root API。它似乎使

querySelectorAll
变得无用,因为
querySelectorAll
实际上不再获得 all 匹配元素,因为它 ignores
shadowRoots
中的所有后代。也许有一个 API 可以解决这个问题,但由于我还没有找到,所以我写了自己的:

此函数递归地迭代所有

shadowRoots
并为您提供all页面上的匹配元素,而不仅仅是单个
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

10
投票

举个例子:

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);

演示:

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>

希望对您有所帮助

© www.soinside.com 2019 - 2024. All rights reserved.