元素不呈现嵌套(子)组件用于复制/粘贴/打印



我试图将复制/粘贴和打印功能添加到嵌套的lite元素树。我试图让嵌套的组件渲染,所以我可以推完整的html+样式在一个字符串到复制/粘贴缓冲区,也到iframe或隐藏的div打印。

代码可以在这里找到:https://mjmihk.stackblitz.io

我的方法是选择父元素并获得阴影DOM的内容,但这似乎会产生"浅渲染"。我希望看到<p>标签嵌套在<child-greeting>标签的边界内。

var elem: any = document.querySelector("simple-greeting");
var cpRoot = elem.shadowRoot.querySelector("#cproot");

当尝试这样做时,复制粘贴内容不会"深度"渲染子元素:

<p>Hello, World!</p>
<child-greeting name="Peter"></child-greeting>
<child-greeting name="Constance"></child-greeting>

任何帮助这里感谢!

在https://stackblitz.com/edit/mjmihk

的源(而不是输出)链接中更容易帮助解决这个问题。首先:

var elem: any = document.querySelector("simple-greeting");

获取document中该组件的第一个实例,因此如果有多个实例将失败。您不需要这样做,因为使用Lit的@语法订阅的任何事件都将以this作为当前元素来调用。

这意味着你的下一行应该是:

const cpRoot = this.shadowRoot.querySelector("#cproot");

然而,有一个更好的方法来获得使用LitElement的@query装饰器:

@query('#cproot') private cpRoot: HTMLDivElement;
_handlePrintClick() {
console.log("copy/paste/print content:", this.cpRoot.innerHTML);
}

你的下一个问题是innerHTML-这得到DOM。有了web组件,你现在有两种类型的文档——你放在组件内部的HTML,以及组件拥有的一个新的独立的HTML。

例如,如果你有:

<child-greeting name="Peter">
#shadow-root [<p>I am the child. ...!</p>]
<p>Something else about Peter</p>
</child-greeting>

(child-greeting有一个<slot>)然后innerHTML会给你<p>Something about Peter</p>,这是轻DOM。您的影子DOM (<p>I am the child. ...!</p>位)不包括在内。

对于大多数自定义元素,正是您想要的,因为影子DOM将保存组件部分-选择或日期选择器上的下拉菜单,富文本输入上的操作按钮等。许多浏览器在内部使用它——例如<video>有影子DOM来渲染播放按钮、进度条等。

你有两个选择:

  1. 在您想要将其内容暴露给innerHTML的元素上打破阴影DOM。你可以通过重写创建阴影DOM片段的方法来返回控件,从而在LitElement中做到这一点:
createRenderRoot() {
return this;
}
  1. 直接访问DOM而不是使用innerHTML。这将需要递归地检查每个元素上的shadowRoot,并且任何使用<slot>的元素将不得不重新构建其DOM树,以将嵌套的轻DOM内容放入其中。

这两种方法都不是特别容易,而且都有妥协。

最新更新