学习 Web Components 组件设计:使用 Shadow DOM

阅读时长 7 分钟读完

前言

在前端开发中,组件化的思想越来越流行。而 Web Components 是将组件化思想带入 Web 标准的重要标志。它提供了一套标准化的 API,让我们可以创建自定义的、可重用的组件。

Web Components 由四个主要技术组成:

  1. Custom Elements:自定义元素,允许我们定义属于自己的 HTML 元素,例如 <my-dialog>、<my-timeline>;
  2. Shadow DOM:影子 DOM,允许我们封装元素内部的实现细节并隐藏它们,同时阻止外部样式和脚本的影响;
  3. Template:模板,允许我们创建可重用的 HTML 模板;
  4. HTML Imports:HTML 导入,允许我们以 HTML 文件的形式导入其他文件。

本文着重介绍 Shadow DOM 的使用,深入讲解其概念、用法和实现,帮助读者更好地理解 Web Components。

Shadow DOM 的概念

Shadow DOM (简称 Shadow)是 Web Components 最重要的技术之一。它实现了一种“隔离”机制,将组件内部的实现细节隐藏在一个内部 DOM 树中(称为 Shadow Tree),同时阻止外部样式和脚本的影响。这意味着我们可以自由地设计组件的外观和内部实现,而不必担心与外部环境的冲突。

Shadow DOM 有以下特点:

  • 影子 DOM 树的根节点是 Shadow Host,它是一个标准的 HTML 元素(或自定义元素)。
  • 影子 DOM 树内部的节点称为 Shadow Tree。它由开发者自己构建,与外部文档树是分离的。开发者可以自由地添加、删除、修改影子 DOM 树中的元素。
  • 影子 DOM 树内部的细节对外部文档树是不可见的。外部样式和脚本对影子 DOM 的样式和行为不会产生影响。开发者需要使用 CSS 的伪类 ::shadow::part 选择器来调用影子 DOM 中的元素。例如:my-dialog::shadow .title { color: red; }
  • 相同的自定义元素类型可以拥有不同的影子 DOM 实现。开发者可以针对具体的使用场景,设计不同的影子 DOM 树,以适应用户需求。

Shadow DOM 的语法和用法

搭建 Shadow DOM

创建 Shadow DOM 的基本步骤如下:

  1. 使用 attachShadow 方法,在一个元素上添加一个 Shadow DOM 节点;
  2. 在 Shadow DOM 内部添加元素和文本节点。

示例代码如下:

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

上面的代码中,我们通过 attachShadow 方法在 <my-dialog> 上添加了一个 Shadow DOM。通过 createElementappendChild 方法,在 Shadow DOM 内部构建了一个 <div> 元素和一个 <h1> 元素。

样式和样式隔离

在 Shadow DOM 中,样式的作用域是局限于影子 DOM 树内部的。这与 Vue 和 React 等框架的 scoped 样式类似。

在样式表中,我们可以使用 :host 伪类选择器来选择 Shadow Host。例如,以下代码使用了 :host 选择器来定义一个全屏对话框的样式:

同时,我们还可以使用 ::part 伪元素选择器来选择 Shadow Tree 内部的元素。例如,以下代码使用了 ::part 选择器来定义对话框标题的样式:

示例代码如下:

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

事件和事件委托

在 Shadow DOM 中,事件的传播和处理方式与普通的 HTML 元素相同。但是,由于 Shadow Tree 是与文档树分离的,因此我们需要将事件委托给含有 Shadow Tree 的元素。

例如,以下代码在 Shadow Host 上添加了一个点击事件监听器,并将事件委托给包裹整个 Shadow Tree 的 <div> 元素:

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

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

在这个例子中,当用户点击组件内部的元素时,事件会沿着 Shadow Tree 的路径冒泡,直到遇到最外层的包裹元素。该元素会检查事件的目标,并触发相应的事件响应函数。

总结

本文介绍了 Web Components 中最重要的技术之一——影子 DOM。我们详细讲解了影子 DOM 的概念、用法和局限性,希望能对读者有所帮助。

影子 DOM 的使用可以提高组件化代码的可重用性、可维护性和可扩展性。但是,与之相应的也带来了更多的开发压力。开发者需要维护更多的代码逻辑和样式实现,同时需要注意影子 DOM 的边界和作用域。

在后续的学习和开发中,我们需要深入理解 Web Components 的各个技术组成部分,量身定制自己的组件库,提高代码的质量和交互的用户体验。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64853dda48841e9894423b74

纠错
反馈