使用 Custom Elements 实现深度联动的省市区选择器及交互设计

阅读时长 16 分钟读完

前端开发中,省市区选择器是常用的业务场景。而实现省市区的深度联动是一个比较具有挑战性的任务,涉及到多个级别之间的数据绑定和联动。本文将介绍如何使用 Custom Elements 实现省市区的深度联动选择器,以及该组件的交互设计。

Custom Elements 的基本概念

Custom Elements 是 Web Components 规范的一部分,可以让开发者创建自定义 HTML 标签,并在其中定义自定义行为。这些自定义标签和行为可以被其他开发者和框架使用和扩展,实现了代码复用和可维护性的提升。

一个 Custom Element 通常包含三个部分:

  • 定义元素类:使用 classprototype 创建一个继承自原生 HTML 元素的自定义元素类。
  • 注册元素:使用 customElements.define() 注册自定义元素,并指定其标签名和元素类。
  • 元素行为:在自定义元素类中实现元素的行为和属性。

在省市区选择器中,我们可以将省、市、区/县作为 Custom Element,分别实现它们之间的联动。

省市区选择器的设计

在设计省市区选择器的交互设计前,我们需要考虑一些问题:

  1. 每个城市的省、市、区级别是不一样的,如何根据输入的数据自动判断哪些级别需要展示?
  2. 如何实现级别之间的联动,用户选择了一个级别后,下一级的数据应该被过滤出来?
  3. 如何保证选择器的显示和行为是符合用户交互体验的?

在回答了这些问题后,我们可以开始设计省市区选择器的交互设计:

1. 级别自适应的展示

在用户输入数据时,我们可以根据数据的内容自动判断哪些级别需要展示,比如某些城市只有省和市,而没有区一级。我们可以自适应的决定应该展示哪些级别。

2. 级别之间的联动

用户选择一个级别后,下一级的数据应该被过滤出来,且选择的级别之后的级别应该被清空。比如如果用户选择了某个省份,市和区的选择应该清空。我们也需要考虑这样一个场景:用户选择了一个区/县,然后又选择了一个省,应该如何处理?我们可以选择保留区/县的选择,但是需要提示用户。

3. 交互体验的优化

在交互体验的优化上,我们需要考虑用户使用场景和习惯,如何让用户快速、简单地选择他们想要的数据?我们可以使用搜索框、快速字母选择、自动补全等方式来提高用户的选择效率。

完成以上设计后,我们可以开始实现省市区选择器。

省市区选择器的实现

在省市区选择器中,我们需要实现三个 Custom Element:province-selectorcity-selectordistrict-selector。它们都继承自原生 HTML 元素,并且实现了以下行为:

  1. 级别自适应的展示。
  2. 级别的联动。
  3. 基于用户输入自动过滤数据。
  4. 提供搜索框和快速字母选择功能。

以下是一个实现了以上功能的 Demo:

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

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

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

-------
展开代码

在以上代码中,我们创建了三个 Custom Element:ProvinceSelectorCitySelectorDistrictSelector

ProvinceSelector 中,我们实现了以下行为:

  1. 在元素被连接到文档流时,向远程获取省份数据,并添加到 select 元素中。
  2. select 元素变化时,派发 provincechangedistrictchangecitychange 事件,通知其余选择器更新状态。
  3. search() 方法中,搜索选项并根据用户输入过滤选项。

CitySelector 中,我们实现了以下行为:

  1. 在元素被连接到文档流时,监听父元素的 provincechange 事件,并根据所选省份从远程获取对应城市数据,并添加到 select 元素中。
  2. select 元素变化时,派发 districtchangecitychange 事件,通知其余选择器更新状态。
  3. search() 方法中,搜索选项并根据用户输入过滤选项。

DistrictSelector 中,我们实现了以下行为:

  1. 在元素被连接到文档流时,监听父元素的 citychange 事件,并根据所选城市从远程获取对应区数据,并添加到 select 元素中。
  2. select 元素变化时,派发 districtchange 事件,通知其余选择器更新状态。
  3. search() 方法中,搜索选项并根据用户输入过滤选项。

在 HTML 中,我们使用 customElements.define() 注册这些 Custom Element,并在 search() 方法中监听用户的输入事件,并依次搜索对应的选项。

在演示中,我们让 DistrictSelector 派发 districtchange 事件,并在控制台输出选项。你可以在此基础上进行更多的扩展,比如在最后添加一个确认按钮,让用户在选择完毕后提交数据。

通过这个 Demo,你可以学习到如何使用 Custom Elements 实现深度联动的省市区选择器及基于用户输入的搜索功能。如果您还有其他关于前端类的问题,欢迎在评论区留言,我们会尽快回复您。

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

纠错
反馈

纠错反馈

程序员教程

精选优质教程,助你快速提升技术实力

程序员面试题库

海量优质面试题,助你轻松应对技术面试