在 Vue.js 中如何实现无限级联选择器?

阅读时长 14 分钟读完

在很多前端开发的项目中,都会遇到需要选择多级联动数据的情况。例如,选择省市区、选择品牌系列型号等。Vue.js 是一款流行的前端框架,其强大的数据绑定和响应式能力使得实现无限级联选择器变得非常容易。

接下来,本文将介绍如何通过 Vue.js 实现无限级联选择器。我们将从原理分析、编写代码、优化性能等方面一步步引导读者完成这项任务。

原理分析

首先我们需要明确,无限级联选择器的核心就是数据。而多级的数据并不是规定的,往往不同的需求数据结构也不一样。例如,我们需要实现选择地址的功能,那么数据结构就应该像这样:

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

每一级数据都有自己的 labelvalue 属性,这用于显示和选中某个选项。而 children 属性则表示该级别下面的子级数据,用于级联显示。

接下来,我们将分析实现无限级联选择器的核心原理:

  1. 定义一个组件用来显示级别的选项
  2. 使用组件递归渲染每一级别的选项

第一步中,我们需要定义一个 CascadeItem 组件,该组件需要根据传入的数据渲染自己的选项并且能够激活下一级选择器。我们可以用以下代码作为 CascadeItem 的基础:

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

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

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

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

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

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

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

其中,我们在 isActive 方法中判断当前级别的值是否等于 selected 中的选中值,并在 handleClick 方法中更新 selected,并清空下级的值,达到级联选择的效果。

接下来我们需要将递归逻辑写成 Cascade 组件。只需要给其一个数组作为初始数据,并且将初始的 selected 置空即可。

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

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

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

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

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

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

最后,我们只需要在使用 Cascade 时传入相应的数据结构即可实现无限级联选择器。

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

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

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

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

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

示例代码

为了更好地理解上面的原理分析,这里提供了一个完整的示例代码:

CascadeItem.vue

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

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

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

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

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

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

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

Cascade.vue

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

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

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

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

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

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

App.vue

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

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

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

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

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

优化性能

在层级比较深的时候,我们的递归渲染容易出现组件重复渲染、频繁切换等问题。为了优化性能,我们可以使用 keep-alive 来对组件进行缓存。

为此,我们需要对 Cascade 中传入的 selected 进行一个小小的处理:

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

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

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

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

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

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

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

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

selected 维护为一个数组,则每一项对应一个层级的选项值。每次添加新的选项值时,我们会更新数组,同时 getSelectedObj() 会返回数组中的最后一项,即当前选中层级对应的对象。

最后,我们只需在 Cascade 中加上一个 keep-alive 组件即可对 CascadeItem 进行缓存:

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

这样做既可以提高性能,又能保证递归渲染结构的正确性。

总结

Vue.js 的数据绑定和响应式机制使得实现无限级联选择器变得非常容易。通过一个递归的选择项组件,加上 selected 级联维护选项值即可实现组件间的无缝链接。在性能优化中,我们可以使用 keep-alive 来进行缓存,防止重复渲染和切换。并且,多层级的数据结构也不会成为阻挡我们写出这种组件的障碍,而是被我们巧妙地处理掉了。

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

纠错
反馈