如何克隆ShadowRoot?

问题描述 投票:17回答:2

我正在尝试克隆阴影根,以便我可以将<content></content>的实例与其相应的分布式节点交换。

我的方法:

var shadowHost = document.createElement('div');
var shadowRoot = shadowHost.createShadowRoot();

var clonedShadowRoot = shadowRoot.cloneNode(true);

不起作用,因为“ShadowRoot节点不可克隆”。

这样做的动机是我希望检索组合的阴影树,以便我可以使用渲染的HTML标记。

由于Shadow DOM的性质,这可能不起作用,克隆过程可能会破坏对分布式节点的引用。

编写影子树很可能是一个原生的功能,但是通过搜索w3c规范,我无法找到这样的方法。

有这样的原生方法吗?或者,如果不这样做,手动遍历(在过程中复制树)会起作用吗?

javascript html html5 dom shadow-dom
2个回答
1
投票

好。这有点疯狂,但这是我写的一个例程,它将克隆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);
.shadow1 {
  background-color: #F88;
}

.shadow2 {
  background-color: #88F;
}
<div class="shadow1">
  <p>SHADOW 1</p>
</div>
<div class="shadow2">
  <p>SHADOW 2</p>
</div>

我不得不从shadowDOM中删除每个节点,然后克隆它,然后将其追加回shadowRoot。

我甚至添加了一个setTimeout,这样你就可以看到它随时可用。

它甚至适用于插槽。


0
投票

也许还有更多你想要完成的东西,但似乎解决无法使用cloneNode的一种方法是创建一个镜像ShadowRoot,然后从原始“克隆”innerHTML。例如:

const shadowRoot = document.createElement('div').attachShadow({mode: 'open'});
shadowRoot.appendChild(document.createElement('p'));
console.log('Original shadow tree', shadowRoot.childNodes);

const cloneRoot = document.createElement('div').attachShadow({mode: 'open'});
cloneRoot.innerHTML = shadowRoot.innerHTML;
console.log('Cloned shadow tree', cloneRoot.childNodes);
© www.soinside.com 2019 - 2024. All rights reserved.