使用 Web Components 构建可复用的模块化 UI 组件

阅读时长 12 分钟读完

前言

Web Components 是一种用于创建可复用的自定义 HTML 元素的技术。它由四个主要的技术组成:Custom Elements、Shadow DOM、HTML Templates 和 ES Modules。使用 Web Components,我们可以创建可复用的模块化 UI 组件,这些组件可以在任何网页中使用,而且不需要其他的框架或库的支持。在本文中,我们将介绍如何使用 Web Components 构建可复用的模块化 UI 组件,以及如何将它们集成到现有的网页中。

Custom Elements

Custom Elements 允许我们创建自定义的 HTML 元素。这些元素可以具有任何名称,并且可以包含自己的属性和方法。要创建自定义元素,我们需要使用 window.customElements.define() 方法。这个方法需要两个参数:元素名称和元素定义对象。元素定义对象包含 extends 属性,该属性指定自定义元素的基类。我们可以将自定义元素继承自任何 HTML 元素,例如 HTMLDivElementHTMLButtonElement

以下是一个简单的示例,其中我们创建了一个名为 my-button 的自定义元素,它继承自 HTMLButtonElement,并添加了一个名为 color 的属性:

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

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

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

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

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

在这个示例中,我们创建了一个名为 MyButton 的类,它继承自 HTMLButtonElement。我们在构造函数中添加了一个点击事件监听器,当用户点击按钮时,会弹出一个对话框。我们还定义了一个名为 color 的属性,并在 observedAttributes 方法中声明,以便在属性值发生变化时进行处理。在 attributeChangedCallback 方法中,我们检查属性名称是否为 color,如果是,则将按钮的文本颜色设置为属性值。最后,我们使用 window.customElements.define() 方法将 MyButton 类定义为名为 my-button 的自定义元素,并继承自 button 元素。

Shadow DOM

Shadow DOM 允许我们将元素的样式和行为封装在一个独立的 DOM 树中,从而避免与其他元素的样式和行为发生冲突。要创建 Shadow DOM,我们需要使用 Element.attachShadow() 方法。这个方法接受一个 ShadowRootInit 对象作为参数,该对象包含 mode 属性,指定 Shadow DOM 的模式。有两种模式可用:openclosedopen 模式允许外部代码访问 Shadow DOM,而 closed 模式不允许。

以下是一个示例,其中我们创建了一个名为 my-dialog 的自定义元素,它包含一个名为 header 的插槽和一个名为 content 的 Shadow DOM:

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

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

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

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

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

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

在这个示例中,我们创建了一个名为 MyDialog 的类,它继承自 HTMLElement。在构造函数中,我们使用 Element.attachShadow() 方法创建了一个 Shadow DOM,并将一个名为 template 的模板元素添加到 Shadow DOM 中。模板元素包含了一些 CSS 样式和 HTML 标记,用于渲染对话框。我们通过 ::slotted() 伪元素选择器对插槽内容进行样式设置,从而将其样式与对话框的样式分离。最后,我们使用 window.customElements.define() 方法将 MyDialog 类定义为名为 my-dialog 的自定义元素。

HTML Templates

HTML Templates 允许我们创建可重复使用的 HTML 片段。这些片段可以包含任何 HTML 标记和文本,并可以在需要时动态地插入到文档中。要创建 HTML 模板,我们可以使用 <template> 标记。

以下是一个示例,其中我们创建了一个名为 my-list 的自定义元素,它使用 HTML 模板来渲染列表项:

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

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

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

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

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

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

在这个示例中,我们创建了一个名为 MyList 的类,它继承自 HTMLElement。在构造函数中,我们创建了一个名为 template 的 HTML 模板,并将其添加到 Shadow DOM 中。模板元素包含了一些 CSS 样式和一个空的 <ul> 元素。我们在 connectedCallback() 方法中遍历子元素,如果子元素是一个名为 my-list-item 的自定义元素,则创建一个 <li> 元素,并将其添加到 <ul> 元素中。最后,我们使用 window.customElements.define() 方法将 MyListMyListItem 类定义为名为 my-listmy-list-item 的自定义元素。

ES Modules

ES Modules 允许我们在 JavaScript 中使用模块化的语法。我们可以使用 importexport 关键字来导入和导出模块。要使用 ES Modules,我们需要在 HTML 中使用 <script type="module"> 标记,以便浏览器知道我们正在使用模块化的 JavaScript。

以下是一个示例,其中我们创建了一个名为 my-clock 的自定义元素,它使用 ES Modules 来导入和使用 Moment.js 库来显示当前时间:

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

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

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

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

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

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

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

在这个示例中,我们创建了一个名为 MyClock 的类,它继承自 HTMLElement。在构造函数中,我们初始化了一些变量,包括一个名为 _intervalId 的变量,用于存储 setInterval() 方法返回的 ID。我们还使用 import 关键字导入了 Moment.js 库,并在 connectedCallback() 方法中启动了一个定时器,每秒钟调用一次 _tick() 方法。在 _tick() 方法中,我们使用 Moment.js 库来获取当前时间,并将其格式化为指定的格式。最后,我们将格式化后的时间设置为元素的 innerHTML

结论

使用 Web Components,我们可以创建可复用的模块化 UI 组件,这些组件可以在任何网页中使用,而且不需要其他的框架或库的支持。在本文中,我们介绍了四个主要的技术:Custom Elements、Shadow DOM、HTML Templates 和 ES Modules。我们还提供了一些示例代码,以便读者更好地理解这些技术。如果您想深入学习 Web Components,请查看官方文档和示例代码库。

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

纠错
反馈