Polymer是Google开发的一个web组件化工具,致力于推动web组件标准化和实现web组件化开发。其中,Polymer Custom Elements是其最为重要的特性之一。在Polymer中,Custom Elements可以使用Shadow DOM,这一特性可以大大提高组件的封装性和可维护性。本文将介绍Polymer Custom Elements的Shadow DOM机制与其与CSS的配合使用方法,并提供示例代码。
Shadow DOM 简介
Shadow DOM是web组件规范的一部分,它为自定义元素提供了一种将其DOM节点和样式封装在一个独立DOM树中的方式。这样,自定义元素的内部节点和样式与外层文档的节点和样式完全隔离,互相之间不会有任何干扰。Shadow DOM由三个部分组成:
- Shadow DOM根:Shadow DOM树的根节点,是一棵完全隔离外界的DOM树。
- Shadow Host:自定义元素的宿主元素,它与Shadow DOM根通过Shadow DOM API联系。
- Shadow Insertion Point:插入点,用于将组件的Shadow DOM插入到文档的特定位置。
Shadow DOM上层接口是将各种生命周期事件以及DOM操作从外部传递到内部,以及从内部传递到外部的接口。
Polymer Custom Elements 的 Shadow DOM
Polymer是基于Web Components规范的自定义元素库,自然而然支持Shadow DOM。Polymer将Shadow DOM封装在一个Polymer元素的内部,允许使用shadow属性来定义一个Shadow DOM。例如:
-- -------------------- ---- ------- ----------- ------------- ---------- ------- ----- - -------- ------ - -- ------ --- -- -- -------- ---- -------------- ---- -------------- ---- ------ --- -- --- ------ ------ ----------- -------- --------- --- ---------- -- ------- ---- -- --- --------- -------------展开代码
在这个例子中,inner
和outer
两个DOM节点以及它们的样式都被封装在了一个Shadow DOM中,并且在Polymer元素中定义了一个包含Shadow DOM的模板。其中,:host
选择器用来定义Polymer元素本身的样式。
在Polymer元素内部,可以通过以下方式获取Shadow DOM的根节点和插入点:
Polymer({ is: "my-elem", created: function() { var root = this.shadowRoot; var insertPoint = root.querySelector("#insertion-point"); } });
Shadow DOM 和 CSS
Shadow DOM的出现加强了web组件的封装性,但同时也加大了样式的复杂性。在使用Shadow DOM时,我们可能会遇到以下问题:
- 组件内部的样式如何覆盖外部文档的样式?
- 组件内部的样式如何能够被外部文档所覆盖?
- 如何在组件内部定义全局样式?
以下是对上述问题的解决方案:
组件内部的样式如何覆盖外部文档的样式?
当外部文档和组件内部使用相同的选择器时,外部文档的样式会覆盖组件内部的样式。为了避免这种情况,可以在组件的选择器前加上:host
前缀:
-- -------------------- ---- ------- ----------- ------------- ---------- ------- ----- ------ - -- ------- -- - -------- ---- -------------- ---- -------------- ---- ---------- --- ------ ------ ----------- -------- --------- --- ---------- -- ------- ---- -- --- --------- -------------展开代码
在这个例子中,:host
前缀用来选择Polymer元素本身,这样就能够覆盖外部文档的样式了。
组件内部的样式如何能够被外部文档所覆盖?
为了让外部文档的样式可以覆盖组件内部的样式,可以在选择器前加上:host-context()
前缀:
-- -------------------- ---- ------- ----------- ------------- ---------- ------- ------------------------ ------ - ------ ------ - -------- ---- -------------- ---- -------------- ---- ---------- --- ------ ------ ----------- -------- --------- --- ---------- -- ------- ---- -- --- --------- -------------展开代码
在这个例子中,:host-context()
前缀用来选择外部文档中包含特定类名的元素,这样就能够被外部文档覆盖。
如何在组件内部定义全局样式?
为了定义全局样式,可以在:host
选择器中定义:
-- -------------------- ---- ------- ----------- ------------- ---------- ------- ----- - -- ---- -- - -------- ---- -------------- ---- -------------- ---- ---------- --- ------ ------ ----------- -------- --------- --- ---------- -- ------- ---- -- --- --------- -------------展开代码
在这个例子中,:host选择器用来定义全局样式。
示例代码
本文提供一个简单的示例来演示Shadow DOM和CSS的使用方法:
-- -------------------- ---- ------- --------- ----- ------ ------ ----- ---------------- -------------- ------ -------- - ------ --- - ----------- ------- ------------------------------------------------------------------------------------ ----- ------------ ----------------------------------------------------------- ------- -- ---- -- --------- - ----------------- ------ ------ ------ - -- ------ -- ------ - ------- --- ----- ---- - -------- ------- ----- ------------- ----------- ------------- ---------- ------- ----- - -------- ------ -------- ----- -- ---- -- ----------------- ----- ------ ----- - ------------------------ ------ - ------ ------ - ----- ------ - -- ------ -- ------- --- ----- ------ ------- ----- -------- ----- ----------------- -------- - -------- ---- -------------- ---- ------------------------------ ------ ----------- -------- --------- --- ---------- -- ------- ---- -- --- --------- ------------- ------------------- ------- -------展开代码
在这个例子中,我们定义了一个my-elem
的Polymer元素,它包含了一个Shadow DOM,并通过CSS进行样式的定义和控制。其中,:host
选择器用来定义全局样式,:host-context()
选择器用来定义外部文档样式,其它选择器用来定义组件内部样式。在body
元素中添加dark
类名可以改变全局样式。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67ca64d1e46428fe9e281136