Polymer Custom Elements 的 shadow dom 与 CSS

阅读时长 8 分钟读完

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由三个部分组成:

  1. Shadow DOM根:Shadow DOM树的根节点,是一棵完全隔离外界的DOM树。
  2. Shadow Host:自定义元素的宿主元素,它与Shadow DOM根通过Shadow DOM API联系。
  3. 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。例如:

-- -------------------- ---- -------
----------- -------------
  ----------
    -------
      ----- -
        -------- ------
      -
      -- ------ --- -- --
    --------
    ---- --------------
      ---- --------------
        ---- ------ --- -- ---
      ------
    ------
  -----------

  --------
    ---------
      --- ----------
      -- ------- ---- --
    ---
  ---------
-------------
展开代码

在这个例子中,innerouter两个DOM节点以及它们的样式都被封装在了一个Shadow DOM中,并且在Polymer元素中定义了一个包含Shadow DOM的模板。其中,:host选择器用来定义Polymer元素本身的样式。

在Polymer元素内部,可以通过以下方式获取Shadow DOM的根节点和插入点:

Shadow DOM 和 CSS

Shadow DOM的出现加强了web组件的封装性,但同时也加大了样式的复杂性。在使用Shadow DOM时,我们可能会遇到以下问题:

  1. 组件内部的样式如何覆盖外部文档的样式?
  2. 组件内部的样式如何能够被外部文档所覆盖?
  3. 如何在组件内部定义全局样式?

以下是对上述问题的解决方案:

组件内部的样式如何覆盖外部文档的样式?

当外部文档和组件内部使用相同的选择器时,外部文档的样式会覆盖组件内部的样式。为了避免这种情况,可以在组件的选择器前加上: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

纠错
反馈

纠错反馈