我试图将复制/粘贴和打印功能添加到嵌套的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来渲染播放按钮、进度条等。
你有两个选择:
- 在您想要将其内容暴露给
innerHTML
的元素上打破阴影DOM。你可以通过重写创建阴影DOM片段的方法来返回控件,从而在LitElement中做到这一点:
createRenderRoot() {
return this;
}
- 直接访问DOM而不是使用
innerHTML
。这将需要递归地检查每个元素上的shadowRoot
,并且任何使用<slot>
的元素将不得不重新构建其DOM树,以将嵌套的轻DOM内容放入其中。
这两种方法都不是特别容易,而且都有妥协。