使用 Custom Elements 和 Shadow DOM 创建独立的 UI 元素

阅读时长 11 分钟读完

在 Web 开发中,我们常常需要使用到复杂的 UI 元素,例如导航菜单、多级下拉框或自定义控件等。为了实现这些 UI 元素的重用和可维护性,我们需要将其封装为独立的组件。而本文将介绍如何使用 Custom Elements 和 Shadow DOM 来创建自定义的独立 UI 元素。

Custom Elements

Custom Elements 是一种浏览器原生支持的 JavaScript API,用于自定义 HTML 元素,使其具备自定义行为和属性。相较于传统的创建 DOM 元素的方式,使用 Custom Elements 可以创建更加优秀的封装组件。

创建 Custom Element

创建 Custom Element 可以使用 window.customElements.define() 方法,该方法需要两个参数:自定义元素的名称和其类定义。下面是一个简单的例子:

在上面的例子中,我们定义了一个名为 HelloWorld 的 Custom Element,并注册了它的标签名为 hello-world。当页面加载时,HelloWorld 元素会自动渲染到页面中,并显示“Hello, World!” 消息。

自定义属性和方法

我们可以通过类属性和方法的方式为 Custom Element 添加自定义属性和行为。例如,我们可以为 HelloWorld 元素添加一个 name 属性,然后在 connectedCallback() 方法中使用该属性:

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

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

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

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

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

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

在上面的例子中,我们为 HelloWorld 元素添加了一个 name 属性,并在 connectedCallback() 方法中使用该属性绘制前缀。我们还将 name 属性定义为 observedAttributes,以便我们可以跟踪任何属性的更改并在 attributeChangedCallback() 方法中反映这些更改。

生命周期回调

当我们使用 window.customElements.define() 方法定义一个 Custom Element 时,它将自动注册以下生命周期回调:

  • constructor() - 元素创建时被调用。
  • connectedCallback() - 元素第一次被连接到文档 DOM 时被调用。
  • disconnectedCallback() - 元素从文档 DOM 中断开连接时被调用。
  • attributeChangedCallback(name, oldValue, newValue) - 元素的某个属性被添加、移除或更改时被调用。

通过覆盖这些回调,在特定生命周期阶段执行自定义逻辑。例如,我们可以在 connectedCallback() 方法中执行初始化逻辑,并在 disconnectedCallback() 方法中执行资源清理逻辑。

Shadow DOM

Shadow DOM 是在 Web 组件中用于封装样式和 DOM 的浏览器原生技术。它允许我们创建真正独立的组件,使其内部结构和样式对外部的 DOM 和样式不起作用。

创建 Shadow DOM

创建 Shadow DOM 可以使用 element.attachShadow() 方法。该方法将创建一个新的 Shadow DOM,并将其附加到指定的元素上。下面是一个创建 Shadow DOM 的例子:

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

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

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

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

在上面的例子中,我们使用 element.attachShadow() 方法创建一个带有 mode: 'open' 选项的 Shadow DOM。该选项允许外部文档访问内部 Shadow DOM 的内容。然后我们向 Shadow DOM 中添加了样式和内容。注意,我们使用了 :host 伪类选择器,以便为自定义元素本身添加样式。

样式隔离

Shadow DOM 的最大好处之一是样式隔离。这意味着我们可以将组件的样式封装在组件本身内部,并与外部文档的其他样式完全隔离。例如,我们可以在 Shadow DOM 中创建一个名为 content 的 div,然后为其添加背景颜色,而且它的样式不会影响外部文档:

在上面的例子中,即使 shadow-dom 类被应用于外部文档中的其他元素,它也不会影响 content div 的样式。

插槽

插槽是另一个 Shadow DOM 的有用功能。它可以在模板中定义一个或多个插槽,并将其填充为元素的内容。例如,我们可以在上面 MyComponent 的例子中使用插槽:

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

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

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

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

在上面的例子中,我们在 MyComponent 元素中定义了一个插槽,并在四周包围了 .content div。这意味着任何放入 my-component 元素中的内容都将填充到插槽中。例如:

上面的 HTML 将在 my-component 内部呈现为:

总结

通过使用 Custom Elements 和 Shadow DOM,我们可以更好地封装和重用 UI 组件,并确保它们的样式和 DOM 不受外部文档的影响。我们还可以通过添加自定义属性和方法来扩展这些组件的行为。下面是一个示例 StarRating 组件,用于表示评级:

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

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

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

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

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

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

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

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

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

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

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

StarRating 组件创建了一个包含五个星星的评级控件,可以通过点击星星进行打分,例如:

上面的 HTML 代码将呈现一个三星评级控件。

参考资料

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

纠错
反馈