简体   繁体   English

从 Shadow DOM 中获取 GetElementById

[英]GetElementById from within Shadow DOM

I have a custom-element with shadow DOM, which listens to attribute target change.我有一个带有 shadow DOM 的自定义元素,它侦听属性target更改。
target is supposed to be the ID of the element which my component is supposed to be attached to. target应该是我的组件应该附加到的元素的 ID。

I've tried using querySelector and getElementById to get the element of the outer DOM, but it always returns null .我尝试使用querySelectorgetElementById来获取外部 DOM 的元素,但它总是返回null

console.log(document.getElementById(target));
console.log(document.querySelector('#' + target));

Both of the above return null .以上都返回null

Is there a way to get a reference to the element in the parent document from within shadow DOM?有没有办法从 shadow DOM 中获取对父文档中元素的引用?

You just have to call Shadow​Root .你只需要调用Shadow Root

this.shadowRoot.getElementById('target') should work. this.shadowRoot.getElementById('target')应该可以工作。

Here's an example, the get syntax will bind an object property to a function.这是一个示例, get语法将对象属性绑定到函数。

get target() {
    return this.shadowRoot.getElementById('target');
}

If target is supposed to be an id, then 如果目标应为ID,则

document.getElementById(target)

is a correct code to get the element by id. 是通过id获取元素的正确代码。 The other code, 其他代码,

document.querySelector(target)

is incorrect, the correct version would be 不正确,正确的版本是

document.querySelector("#" + target)

The very fact that you get null as a result for the first means that there is no tag in the document with the id you specified. 第一个结果为null事实意味着,在document没有使用您指定的id标签。 It might have been changed/removed, if it ever existed, or you might want to reach the id of another page's tag. 它可能已被更改/删除(如果曾经存在),或者您可能想获取另一个页面标签的ID。

There are two use cases of shadow DOM as far as I can see:据我所知,shadow DOM 有两个用例:

  1. You control the the shadow DOM solely through your hosting custom element (like in the answer of @Penny Liu).仅通过托管自定义元素来控制 shadow DOM(如@Penny Liu 的回答)。 If you want make sure no other script should call and alter the nodes than this is your choice.如果您想确保没有其他脚本应该调用和更改节点,这是您的选择。 Pretty sure some banking websites use this method.很确定一些银行网站使用这种方法。 You give up on flexibility though.但是你放弃了灵活性。

  2. You just want to scope some parts of your code for styling reasons but you like to control it via document.getElementById than you can use <slot> .出于样式原因,您只想限制代码的某些部分,但您喜欢通过 document.getElementById控制它,而不是使用<slot> After all, many libraries rely on the document object and will not work in shadow DOM.毕竟,许多库依赖于文档对象,在影子 DOM 中不起作用。

Back to the problem, what you probably did was something like this:回到问题,你可能做的是这样的:

shadowRoot.innerHTML = `...<script>document.getElementById('target')</script>`
// or shadowRoot.appendChild

This is NOT working!这是行不通的! And this is not how shadow DOM was anticipated to work either.这也不是 shadow DOM 预期的工作方式。

Recalling method 2 , you SHOULD fill your shadow DOM solely by <slot> tags.回顾方法 2 ,你应该只用<slot>标签填充你的 shadow DOM。 Most minimal example:最简单的例子:

<!-- Custom Element -->
<scoped-playground>
  <style>some scoped styling</style>
  <div id="target"></div>
  <script>const ☝☝☝☝ = document.getElementById('target')</script>
</scoped-playground>

<!-- Scoped playground has a shadowRoot with a default <slot> -->
...
this.shadowRoot.innerHTML = "<slot>Everything is rendered here</slot>";
...

More advanced <slot> examples can be found at:可以在以下位置找到更高级的<slot>示例:
https://developers.google.com/web/fundamentals/web-components/shadowdom#composition_slot https://developers.google.com/web/fundamentals/web-components/shadowdom#composition_slot

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM