Vix*_*Vix 17 html javascript html5 dom shadow-dom
我正在尝试克隆一个影子根,以便可以将<content></content>它们的实例与它们相应的分布式节点交换。
我的方法:
var shadowHost = document.createElement('div');
var shadowRoot = shadowHost.createShadowRoot();
var clonedShadowRoot = shadowRoot.cloneNode(true);
Run Code Online (Sandbox Code Playgroud)
不起作用,因为“ ShadowRoot节点不可克隆”。
这样做的动机是希望检索组成的阴影树,以便可以使用呈现的HTML标记。
由于Shadow DOM的性质,这可能不起作用,对克隆节点的引用很可能会破坏对分布式节点的引用。
组成影子树可能是本机功能,但是在搜索了w3c规范后,我找不到这种方法。
有这样的本机方法吗?否则,手动遍历(在过程中复制树)会起作用吗?
如果您尝试深度克隆可能包含一个或多个嵌套影子树的节点,那么您将需要从该节点遍历 DOM 树并沿途检查影子根。如果对之前提出了有缺陷的浅克隆方法的答案感兴趣,请参阅编辑历史记录。
const deepClone = (host) => {
const cloneNode = (node, parent) => {
const walkTree = (nextn, nextp) => {
while (nextn) {
cloneNode(nextn, nextp);
nextn = nextn.nextSibling;
}
};
const clone = node.cloneNode();
parent.appendChild(clone);
if (node.shadowRoot) {
walkTree(node.shadowRoot.firstChild, clone.attachShadow({ mode: 'open' }));
}
walkTree(node.firstChild, clone);
};
const fragment = document.createDocumentFragment();
cloneNode(host, fragment);
return fragment;
};
// Example use of deepClone...
// create shadow host with nested shadow roots for demo
const shadowHost = () => {
const host = document.createElement('div');
const nestedhost = document.createElement('p');
nestedhost.attachShadow({mode: 'open'}).appendChild(document.createElement('span'));
host.attachShadow({mode: 'open'}).appendChild(nestedhost);
return host;
};
// return fragment containing deep cloned node
const fragment = deepClone(shadowHost());
// deep cloned node
console.log(fragment.firstChild);
// shadow tree node
console.log(fragment.firstChild.shadowRoot.firstChild);
// nested shadow tree node
console.log(fragment.firstChild.shadowRoot.firstChild.shadowRoot.firstChild);Run Code Online (Sandbox Code Playgroud)
好的。这有点疯狂,但这是我编写的一个例程,它将克隆 ShadowRoot 的子级。这符合 V1 规范。
function cloneShadow(shadow) {
const frag = document.createDocumentFragment();
var nodes = [...shadow.childNodes];
nodes.forEach(
node => {
node.remove();
frag.appendChild(node.cloneNode(true));
shadow.appendChild(node);
}
);
return frag;
}
const s1 = document.querySelector('.shadow1');
const s2 = document.querySelector('.shadow2');
s1.attachShadow({mode:'open'}).innerHTML = `<h1>Header</h1>
<p>Content in a paragraph</p><slot></slot>`;
setTimeout(() => {
s2.attachShadow({mode:'open'}).appendChild(cloneShadow(s1.shadowRoot));}, 1000);Run Code Online (Sandbox Code Playgroud)
.shadow1 {
background-color: #F88;
}
.shadow2 {
background-color: #88F;
}Run Code Online (Sandbox Code Playgroud)
<div class="shadow1">
<p>SHADOW 1</p>
</div>
<div class="shadow2">
<p>SHADOW 2</p>
</div>Run Code Online (Sandbox Code Playgroud)
我必须从shadowDOM 中删除每个节点,然后克隆它,然后将其附加回shadowRoot。
我什至添加了一个,setTimeout以便您可以随时看到它是否有效。
它甚至可以与插槽一起使用。