这里是自定义元素的小提琴演示:https://jsfiddle.net/c4bLo097/5/
这是小提琴中的代码:
JavaScript:
window.customElements.define('test-element', class TestElement extends HTMLElement {
constructor() {
super()
let contents = `
<style>
:host {
display: block;
}
:host([hidden]) {
display: none;
}
</style>`
// convert string to nodes
let template = document.createElement('template')
template.innerHTML = contents
// create shadow
this.attachShadow({mode: 'open'})
// insert nodes
this.shadowRoot.appendChild(template.content.cloneNode(true))
}
})
HTML:
<test-element>
This element should have a natural height.
<div style="height: 300px;"></div>
I should be able to see this text on a green background.
</test-element>
CSS:
test-element {
width: 200px;
background: green;
}
如果使用开发者工具检查<custom-element>
,则应该看到阴影存在。但是我的元素无法正确显示其高度。
这里是我要达到的目标的一个例子:https://jsfiddle.net/9483s1qb/2/
谢谢
当添加shadowDOM时,元素的内容将变为“ lightDOM”。.
它不再是您的ShadowDOM的不再显示在主DOM中和not的一部分。
作为Supersharp explained in 2017:
Light DOM只是HTML元素内的普通DOM树。
该术语仅在Web组件(带有Shadow DOM的自定义元素)的上下文中使用我想将普通DOM与Shadow相对地重新定义为Light。
The WHATWG specs称为Shadowroot主机的节点树或轻树:
影子DOM是添加的DOM,用于恢复,掩盖或替换普通DOM,如the article from Google中所述。
customElements.define('my-element', class extends HTMLElement { constructor() { super() //create shadowDOM (thus creating lightDOM) and append Template this.attachShadow({mode: 'open'}) .append(document.getElementById(this.nodeName).content.cloneNode(true)) } connectedCallback(){ //append content from lightDOM this.shadowRoot.append(...this.querySelectorAll('DIV')); } })
my-element{ border: 1px dashed blue; }
<template id="MY-ELEMENT"> <style> :host { display: block; font-size:20px; } h4{ background:yellow; margin: .5em 0; } div{ background:lightcoral; } </style> <h4><slot name="title"></slot></h4> </template> <my-element> <!-- begin lightDOM because my-element has shadowDOM --> <span slot="title">whole SPAN is slotted</span> <div>I am appended</div> <div>appended too</div> <p>I remain (invisible) in lightDOM</p> <!-- end lightDOM --> </my-element> <my-element> <!-- begin lightDOM because my-element has shadowDOM --> <span slot="title">slotted too</span> <div>appended again</div> I remain (invisible) in lightDOM <!-- end lightDOM --> </my-element>
注意:
模板是cloned
] >>connectedCallback
中的[[append
template
一样克隆它。slot="title"
span
(包括跨度!)到shadowDOM中其插槽的位置尝试一下:
<slot></slot>
?如果将<span>
更改为<div>
当尚未实例化(主)DOM时,您可能会[[require setTimeout
中的connectedCallback
:
connectedCallback() {
let savedHTML = this.outerHTML;
//append content from lightDOM
const append = (selector) =>
this.shadowRoot.append(...this.querySelectorAll(selector), savedHTML);
if (this.outerHTML.includes("timeout"))
setTimeout(() => append('DIV'))
else
append('DIV');
}
JSFiddle操场:https://jsfiddle.net/CustomElementsExamples/bzvLcxfe/
中黄色元素DIV附加在[[first
setTimeout
在second中的黄色元素DIV附加了with
[setTimeout
outerHTML
(在[[in connectedCallback
中是已知的])附加在两个元素中。
not
可用,需要setTimeout
才能将代码延迟到事件循环结束并且lightDOM可用。setTimeout
是必需的