用 Custom Elements 构建可重用的 Web Components

阅读时长 13 分钟读完

Web Components 是可重用的颗粒化 UI 组件,可以大幅提升 Web 开发效率。Custom Elements 是 Web Components 的核心部分,它们允许开发者定义自己的 HTML 标签,让标准的浏览器在渲染时可以像普通的 HTML 标签一样处理它们。这篇文章将着重介绍如何用 Custom Elements 创建可重用的 Web Components。

Custom Elements 概述

Custom Elements 是 Web Components 的核心部分,它通过 ES6 的 classextends 语法,可以让我们定义自己的 HTML 标签,使它们拥有自己的行为和样式。具体说来,Custom Elements 可以让我们:

  1. 定义新的 HTML 元素
  2. 定义 HTML 元素的行为和属性
  3. 监听 HTML 元素的生命周期事件

Custom Elements 由两个主要部分组成:

  1. 自定义元素注册 (custom element registration)
  2. 用户定义的自定义元素类 (user-defined custom element classes)

注册 Custom Elements

为了将 Custom Elements 注册到浏览器中,我们需要使用 customElements.define() 方法。这个方法的第一个参数是我们要定义的标签名,第二个参数是继承自 HTMLElement 的类。举个例子,我们可以创建一个自定义元素 MyElement,代码如下:

在上面的代码中,我们定义了自定义元素 my-element,它继承自 HTMLElement 类,它的构造函数在自定义元素被创建时执行。自定义元素注册完成后,我们就可以在页面中使用它了。

继承 HTMLElement 类

Custom Elements 通过继承 HTMLElement 类,让我们的自定义元素获得了标准的 HTML 元素特性。 HTMLElement 类有一些常用的属性和方法,如下:

  • shadowRoot: 这是创建 Shadow DOM 的 API,可以在 Shadow DOM 中定义样式和 HTML 结构。
  • attachShadow(): 这是创建 Shadow DOM 的方法,可以将 Shadow DOM 附加到当前元素上。
  • setAttribute(): 设置元素的属性。
  • getAttribute(): 获取元素的属性。
  • removeAttribute(): 移除元素的属性。

除了以上方法,HTMLElement 类还拥有容许访问 DOM 树的所有其他方法和属性。Web 开发者熟悉的诸如 innerHTMLstyleclassList 等属性和方法,都是从 HTMLElement 类中继承而来的。

自定义元素类实现

自定义元素类需要实现两个方法:constructor()connectedCallback()

constructor()

Custom Elements 会在我们定义的自定义元素被实例化时调用 constructor() 方法。在这个方法中,我们可以初始化元素的状态、属性和事件。

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

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

connectedCallback()

当我们把自定义元素添加到 DOM 树中时,Custom Elements 会调用 connectedCallback() 方法。在这个方法中,我们可以初始化元素的样式、Shadow DOM 和事件。

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

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

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

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

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

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

属性和方法

当我们创建自定义元素后,在使用时可以为它添加属性和方法,这样我们就可以在应用中将自定义元素当做常规 HTML 元素来使用。在自定义元素中,我们可以通过 setAttribute() 方法来设置属性,通过 getAttribute() 方法来获取属性。

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

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

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

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

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

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

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

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

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

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

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

在上面的代码中,我们重载了 Custom Elements 提供的静态 observedAttributes 方法,指定我们希望监听的属性名称列表。当这些属性发生变化时,Custom Elements 就会调用 attributeChangedCallback() 方法。在 render() 方法中,我们在 Shadow DOM 中添加元素,并使用一些已知的属性来更新它们的样式。

使用自定义元素时,我们可以设置它的属性来改变样式。

我们也可以通过访问自定义元素的方法来改变它的状态。

组合和覆盖元素

Custom Elements 允许我们在元素和多个子元素之间建立关系。最常见的办法是通过组合(composition)把多个元素组合到一起。在 Shadow DOM 中,我们可以通过添加子元素来达到这个目的。

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

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

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

在上面的代码中,我们定义了一个自定义元素 MyButton。在 connectedCallback() 方法中,我们使用了 innerHTML 属性来添加一个包含 <style><button> 子元素的 Shadow DOM。在 <button> 元素内,我们使用了 <slot> 元素来表示它包含的内容。在使用 MyButton 时,它会把按钮组件和传递给它的内容组合在一起。

另一方面,Custom Elements 还支持元素的覆盖(extending)。这种情况下,子元素可以把父元素的一些行为修改或扩展为更具体的形式。例如,我们可以创建一个 my-input 元素来扩展 HTML5 的 input 元素。

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

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

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

在上面的代码中,我们继承了 HTMLInputElement 类,并将它的 constructor() 方法调用委托给它的父类。connectedCallback() 方法中,我们将 value 属性设置为 "hello"。由于我们设置了 extends: 'input',所以我们的自定义元素会扩展 HTML5 的 input 元素。在使用 my-input 元素时,HTML5 的其他属性和方法(如 typedisabledfocus() 等)都是可用的。

总结

Custom Elements 是 Web Components 技术的核心,它允许我们创建可重用的 UI 组件,并且在标准的浏览器中以普通 HTML 的方式使用。通过自定义元素注册和继承 HTMLElement 类,我们可以创建具有自定义功能和样式的 HTML 元素。在自定义元素类的定义中,我们可以重载生命周期方法来自定义元素的行为和属性。通过 Shadow DOM,我们可以把元素和子元素组合在一起,创建出更复杂的 UI 组件。Custom Elements 技术可以大幅提升 Web 开发效率,使前端工具更加规范化,更加易于维护。

示例代码

完整的自定义元素和继承 HTMLElement 类的示例代码如下:

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

完整的继承 HTMLInputElement 类的示例代码如下:

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

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

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

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

纠错
反馈