基于 Web Components 构建动态表单组件

阅读时长 19 分钟读完

在现代 Web 开发中,表单是一个不可或缺的组件。然而,传统的表单开发存在一些问题:

  • 表单元素之间缺乏组合能力,无法自由定制布局;
  • 表单验证逻辑难以复用,需要手动编写大量重复代码;
  • 单页面应用(SPA)中切换路由时,表单状态容易丢失。

Web Components 是一种标准化的技术,可以用来解决上述问题。本文将介绍如何基于 Web Components 构建动态表单组件,并演示如何使用该组件来生成一份具有复杂验证逻辑的表单。

Web Components 概述

在 Web Components 中,有三个主要的技术:

  • Custom Elements:可以用来定义自定义 HTML 元素;
  • Shadow DOM:可以用来封装元素的样式和行为,避免影响全局样式;
  • HTML Templates:可以用来定义复杂的 HTML 结构,并在需要时进行实例化。

使用 Web Components 可以将一个组件的样式、DOM 和行为全部封装起来,从而实现组件之间的隔离和复用。

动态表单组件的实现

接下来,我们将使用 Web Components 来开发一个动态表单组件。该组件具有以下功能:

  • 支持自定义表单元素类型和数量;
  • 支持基本的表单验证逻辑,例如检查必填项、检查长度等;
  • 支持自定义验证逻辑,例如检查两个密码输入是否一致等。

定义 Custom Element

首先,我们需要使用 Custom Elements 定义一个新的 HTML 元素。在该元素内部,我们将使用 Shadow DOM 来封装样式和行为。

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

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

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

在上面的代码中,我们定义了一个名为 DynamicForm 的 Custom Element。在构造函数中,我们首先调用了 super(),然后使用 attachShadow() 方法创建了一个新的 Shadow DOM。接下来,我们通过 HTML 模板来定义了组件的样式和内部结构。这里我们使用了 <slot> 元素来实现组件内部可插入元素的特性。

最后,我们调用 customElements.define() 方法来将该组件定义为一个新的 HTML 元素,并使用名称 dynamic-form 进行注册。

插入表单元素

接下来,我们将在组件内部插入表单元素。我们希望用户可以通过属性或方法来定义表单元素的类型和数量。具体实现如下:

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

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

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

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

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

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

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

上面的代码中,我们在组件内部使用了 <form> 元素来包裹表单元素。在实例化时,我们通过 querySelector() 方法获取了 <form> 元素的引用,并保存到了类的实例属性中。

接着,我们重写了 observedAttributes 方法,并返回一个包含我们需要监听的属性名的数组。当某个被监听的属性发生变化时,系统会自动调用 attributeChangedCallback() 方法。

attributeChangedCallback() 方法中,我们首先判断属性名是否为 elements,然后解析出属性值并存储到类的实例属性中。接着,我们调用 renderFormElements() 方法来重新生成表单元素,并将其插入到 <form> 元素中。

表单验证

当表单数据提交时,我们需要对表单进行验证。下面是一些常见的表单验证逻辑:

  • 必填项不能为空;
  • 邮箱地址必须是合法的;
  • 密码必须包含数字和字母,并且长度至少为 8 个字符。

现在,我们将实现这些验证逻辑,并将其封装为组件的方法。

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

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

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

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

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

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

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

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

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

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

在上面的代码中,我们定义了 validateForm() 方法,该方法将遍历表单中的每个输入框,并执行相应的验证逻辑。例如,对于必填项,我们将检查输入框的内容是否为空;对于邮箱地址,则使用正则表达式进行检查。如果某个输入框未通过验证,则将其加上一个 .error 类,方便用户进行识别。

onSubmit() 方法中,我们首先调用 event.preventDefault() 来阻止默认的表单提交行为。接着,我们调用 validateForm() 方法来检查表单数据是否合法。如果合法,则使用 dispatchEvent() 方法触发一个名为 submit 的自定义事件,并将表单数据作为事件的参数传递给外部。至此,我们的动态表单组件已经实现了基本的功能。

自定义规则

最后,我们将介绍如何实现自定义的验证规则。例如,我们希望用户可以指定两个密码输入框的值相等,这可以通过自定义规则来实现。首先,我们需要在组件的属性中添加一个密码确认框元素。

然后,我们在 validateForm() 方法中添加了对自定义规则的支持。

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

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

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

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

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

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

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

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

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

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

在以上代码中,我们将自定义规则表示为 equal_to:password 的形式,其中 password 为另外一个输入框的 name 属性值。在遍历表单元素时,我们对 equal_to: 前缀进行检查,并提取出另一个输入框的名称。然后,我们使用 querySelector() 方法来查找该输入框,并获取其实际的值。最后,我们仅当两个输入框的值相等时,才将其判定为合法的表单。

使用示例

我们已经编写了一个功能齐全的动态表单组件,现在可以在实际项目中使用。下面是一个使用示例:

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

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

在上面的示例中,我们通过设置 elements 属性来定义表单元素,并使用外部脚本来监听表单提交事件。当用户点击提交按钮时,表单验证通过时,我们将使用 alert() 方法显示表单数据的 JSON 字符串表示。在实际项目中,我们可以将 alert() 方法换成发送 AJAX 请求的代码,以便将表单数据发送给后端服务器。

总结

在本文中,我们通过 Web Components 技术的组合使用,实现了一个动态表单组件。该组件具有基本的表单验证功能,并且支持自定义验证规则。我们相信该组件将会在前端开发项目中发挥重要的作用。我们也建议读者深入研究 Web Components 技术,并将其运用到日常的前端开发工作中。

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

纠错
反馈