![](/img/trans.png)
[英]How to access host element from within the shadow root using Shadow DOM v1?
[英]Access Element from within Shadow DOM
我创建了一个 Web 组件,并希望从组件内访问元素。
正在使用 .attachMode({mode:'closed'}),因此父级无权访问。
<template id='hello-world-template'>
<span id='inside'>Unchanged,</span> <span id='outside'>Unchanged</span>
<script>
document.querySelector('#inside').innerHTML = 'Changed';
// Ideal, but does not work - no such element
</script>
</template>
<hello-world></hello-world>
<script>
customElements.define('hello-world',
class extends HTMLElement {
constructor() {
super();
var template = document.getElementById('hello-world-template')
var clone = template.content.cloneNode(true)
const shadowRoot = this.attachShadow({mode: 'closed'}).appendChild(clone);
}
connectedCallback() {
this.shadowRoot.querySelector('#outside').innerHTML = 'Changed';
// Not ideal, and also does not work - this.shadowRoot has no querySelector
}
});
</script>
一些尝试:
我有一个有效的 hack,但无法想象我必须使用它。
封装的全部意义在于事物可以是自包含的,但是如果 JS 不能对其容器中的其他项进行操作,这对我们有什么好处?
如果这是解决方案,希望有一个技巧来解释实现组件的方式的逻辑。
不过,这里有一个技巧:包含一个运行 JS onload 的图像。
<template id='hello-world-template'>
<span id='inside'>Unchanged,</span> <span id='outside'>Unchanged</span>
<script>
function runner(img){
let doc = img.parentNode;
doc.querySelector('#inside').innerHTML = 'Changed';
}
</script>
<img src='data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' onload="runner(this)">
</template>
<hello-world></hello-world>
关于类似问题的注意事项( 25048359 、 16633057 、 55101967等) - 当模式关闭时,这些答案将不起作用,这是我需要的。
看起来您在 Element 引用和this
Scope 中都有错误(在<script>
)
const shadowRoot = this.attachShadow({mode: 'closed'}).appendChild(clone);
appendChild
是你的复仇女神。 它返回插入的元素......不是影子根而是#document-fragment
(克隆模板)
固定:
const shadowRoot = this.attachShadow({mode: 'closed'});
shadowRoot.appendChild(clone);
然后:
mode:closed
不会分配this.shadowRoot
..固定:
this.Root = this.attachShadow({mode: 'closed'});
this.Root.appendChild(clone);
你现在可以这样做:
connectedCallback() {
this.Root.querySelector('#outside').innerHTML = 'Changed';
}
我不明白你为什么认为这不理想
this.Root
可以从组件内的所有/任何方法访问
所有 DOM 方法的一个很好的资源是: https : //javascript.info/modifying-document
<script>
<template>
<script>
内的<script>
(此范围)<template id='hello-world-template'>
<span id='inside'>Unchanged</span>
<script>
document.querySelector('#inside').innerHTML = 'Changed';
// Ideal, but does not work - no such element
</script>
</template>
您将模板注入到组件中
document
无法访问任何组件 shadowDOM内的元素
shadowDOM 是mode:closed
还是mode:open
无关紧要
<script>
范围将是window
(因为它没有分配范围)
(我认为您不能为 SCRIPT 设置此范围)
要在<script>
获取 Component 范围,您必须具有创造性..
并使用您的img onload=
' hack'
随着<style>
元素上的onload
,它变得不那么黑客了(恕我直言)
<template id='hello-world-template'>
<span id='inside'>Inside Unchanged,</span>
<script>
function templFunc() {
// this scope is the shadowRoot, not the component!
this.querySelector('#inside').innerHTML = 'Changed';
}
</script>
<style onload="templFunc.apply(this.getRootNode())">
#inside{
color:green;
}
</style>
</template>
一个主要问题:只会对第一个使用的<hello-world>
元素执行!!
我没有在头顶写这个,
(正在进行中)JSFiddle 游乐场(还显示了引用组件方法)位于:
https://jsfiddle.net/CustomElementsExamples/zpamx728/
Chromium (Edge/Chrome) 和 Opera 很好,FireFox v72.0.2
:
所述onload
上的<STYLE>
元素将仅针对所述第一元件
我使用<img>
更改了 JSFiddle 以使用您的第一个 hack,并且它为每个元素触发
templFunc()
在 shadowDOM 中加载/作用域,因此可以从组件方法调用(参见 JSFiddle)
但是.. 仅在 FireFox 中未为第一个元素定义/可用
现在我认为这是一个 FireFox 错误......将进一步调查......(大胆地去哪里......)
哎呀! 玩了一些。
从克隆和导入的 SCRIPT 中生成所有变量和函数
被提升到全局window
范围
所以上面的代码有效,但有一个主要的副作用......
这也是 FireFox 抱怨重新声明let
变量的原因
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.