我创建了一个 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>
一些尝试:
- 在文档片段中 - this、self、window 和 document 都引用父窗口。而且没有人可以访问影子根。
- 尝试将 shadowroot 存储在全局变量中,并从片段或 connectedCallback 内部访问它。
即使这样可行,它也会破坏使用 {mode:'closed'} 的意义,但无论如何它都不起作用。
我有一个有效的黑客,但无法想象我必须使用它。
封装的全部意义在于事物可以是自包含的,但是如果 JS 不能作用于其容器中的其他项目,那对我们有什么好处呢?
如果这是解决方案,希望有一个提示来解释组件实现方式的逻辑。
不过,这是 hack:包含一个运行 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等)的注意事项 - 当我需要关闭模式时,这些答案将不起作用。