如何设计自定义元素的 API

阅读时长 11 分钟读完

引言

在 Web 开发中,自定义元素是 DOM 中的一部分,其允许我们创建属于我们自己的 HTML 标签,并为这些标签自定义属性和方法。通常情况下,我们往往使用自定义元素来扩展标准的 HTML 元素,也就是说,我们可以为自定义元素增加与原有元素不同的特性或功能。

本篇文章将讨论如何设计自定义元素的 API,如何使用 JavaScript 定义自定义元素,并为之定义属性、方法、事件等等。我们将通过一个实战案例来详细说明如何设计一个自定义元素的 API。

实战案例

我们将以一个自定义的图片上传组件为例进行说明。首先,让我们定义一个 easy-upload 的自定义元素,然后我们可以为其包含一系列属性、方法和事件,来使这个组件变得更加实用和易用。

定义自定义元素

定义自定义元素需要使用 customElements.define 方法,这个方法接收两个参数,第一个参数是元素的名称,第二个参数是一个对象,用来描述该元素的行为和特征。

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

  -- ---
-

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

定义属性

我们需要为组件定义一些属性,以便在 html 中使用该元素时传入一些信息。作为开发者,我们需要考虑使用者在使用这个组件时可能需要什么属性,然后在组件中定义这些属性。

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

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

  -- ---
-

我们需要在 observedAttributes 中列出我们打算定义的属性名称。当这些属性发生变化时,会执行 attributeChangedCallback 方法。

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

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

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

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

  -- ---

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

在构造函数中,我们将定义的属性初始化为 null 或默认值。我们也创建了一个 input 元素,并将其类型设置为 file,用于在选择文件后触发上传操作。

attributeChangedCallback 函数中,我们将每个变化的属性的值保存到组件的属性中。

定义方法

接下来,我们需要定义一些公共方法,方便使用者来控制组件的行为。

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

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

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

我们声明了 uploadreset 两个方法,分别用于触发上传操作和重置上传状态。

定义事件

自定义元素还可以定义事件,以便与外部代码进行交互。

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

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

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

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

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

  -- ---
-

我们在类中用 get onupload/set onupload 的方式定义了上传事件 upload,事件对象包含了已经选择的文件列表。我们在类中还定义了取消上传事件 cancel。这些事件可以在组件中进行触发,方便外部代码进行响应。

完整示例代码

下面是完整的实现示例:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

总结

通过这个实例,我们可以看到,设计一个好的自定义元素 API 不仅需要考虑元素本身的行为和特征,还要考虑使用者的需求和使用场景。在定义自定义元素时,我们需要确定元素的名称、定义属性和方法、触发事件等等。如果我们充分考虑这些因素,就可以设计出更加实用、方便、易用的组件。

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

纠错
反馈