前端开发中,省市区选择器是常用的业务场景。而实现省市区的深度联动是一个比较具有挑战性的任务,涉及到多个级别之间的数据绑定和联动。本文将介绍如何使用 Custom Elements 实现省市区的深度联动选择器,以及该组件的交互设计。
Custom Elements 的基本概念
Custom Elements 是 Web Components 规范的一部分,可以让开发者创建自定义 HTML 标签,并在其中定义自定义行为。这些自定义标签和行为可以被其他开发者和框架使用和扩展,实现了代码复用和可维护性的提升。
一个 Custom Element 通常包含三个部分:
- 定义元素类:使用
class
或prototype
创建一个继承自原生 HTML 元素的自定义元素类。 - 注册元素:使用
customElements.define()
注册自定义元素,并指定其标签名和元素类。 - 元素行为:在自定义元素类中实现元素的行为和属性。
在省市区选择器中,我们可以将省、市、区/县作为 Custom Element,分别实现它们之间的联动。
省市区选择器的设计
在设计省市区选择器的交互设计前,我们需要考虑一些问题:
- 每个城市的省、市、区级别是不一样的,如何根据输入的数据自动判断哪些级别需要展示?
- 如何实现级别之间的联动,用户选择了一个级别后,下一级的数据应该被过滤出来?
- 如何保证选择器的显示和行为是符合用户交互体验的?
在回答了这些问题后,我们可以开始设计省市区选择器的交互设计:
1. 级别自适应的展示
在用户输入数据时,我们可以根据数据的内容自动判断哪些级别需要展示,比如某些城市只有省和市,而没有区一级。我们可以自适应的决定应该展示哪些级别。
2. 级别之间的联动
用户选择一个级别后,下一级的数据应该被过滤出来,且选择的级别之后的级别应该被清空。比如如果用户选择了某个省份,市和区的选择应该清空。我们也需要考虑这样一个场景:用户选择了一个区/县,然后又选择了一个省,应该如何处理?我们可以选择保留区/县的选择,但是需要提示用户。
3. 交互体验的优化
在交互体验的优化上,我们需要考虑用户使用场景和习惯,如何让用户快速、简单地选择他们想要的数据?我们可以使用搜索框、快速字母选择、自动补全等方式来提高用户的选择效率。
完成以上设计后,我们可以开始实现省市区选择器。
省市区选择器的实现
在省市区选择器中,我们需要实现三个 Custom Element:province-selector
、city-selector
和 district-selector
。它们都继承自原生 HTML 元素,并且实现了以下行为:
- 级别自适应的展示。
- 级别的联动。
- 基于用户输入自动过滤数据。
- 提供搜索框和快速字母选择功能。
以下是一个实现了以上功能的 Demo:
-- -------------------- ---- ------- --------- ----- ------ ------ -------- ----- ---------------- ------- ----------- - ------------- - -------- -------------- - - -------- ------- -------- -------- --------------------- --------- -- ------------- - ----------------------------- ------------- - ---------- ----------- - ---------- - ------------------- - ---------------------------- -- - ----------- - ----- --- ---- ---- -- ------------ - ------------------------ ----------------- ------------ - --- ---------------------------------------- ------- -- - ----- ---- - ------------------- ----- ---- - -------------------- -- ------ --- ------ -- -------------- --- ----- - ------- - ------------- - ----- ---------------------- ----------------------------- - ------- - --------- ----- ----- ---------- --------- ---------- -- ---- ---------------------- ----------------------------- - ------- - --------- ----- ----- ---------- --------- ---------- -- ---- ---------------------- ------------------------- - ------- - --------- ----- ----- ---------- --------- ---------- -- ---- --- - ----------- - ------ ------------------------------------------------------- ---------------- -- ---------------- ------------ -- ---------------- - --------------- - --------------------------------------------------------- -- - -- - ----------------------------- --- -- -- --------------------------------- --- -- - - -------------------- - --- - ---- - -------------------- - ------- - --- - - ----- ------------ ------- ----------- - ------------- - -------- -------------- - - -------- ------- -------- -------- --------------------- --------- -- ------------- - ----------------------------- ------------- - ---------- -------------- - ---------- - ------------------- - ----------------------------------------------------- ------- -- - ------------- - ---------- ----------------------- - --- ------------------------ ------------- ----- -- ----------------------- - ----- -------- - ------------------------------ -- --- -------------- - --------- --- ---- -------- -- --------- - ------------------------ --------------------- ---------------- - - ---- - -------------- - ---------- - --- ---------------------------------------- ------- -- - ----- ---- - ------------------- ----- -------- - ----------------------- -- ------ --- ------ -- -------------- --- ----- - ------- - ------------- - ----- ---------------------- ------------------------- - ------- - ----- --------- --------- ---------- -- ---- ---------------------- ----------------------------- - ------- - ----- --------- --------- ---------- -- ---- --- - --------------- - --------------------------------------------------------- -- - -- - ----------------------------- --- -- -- --------------------------------- --- -- - - -------------------- - --- - ---- - -------------------- - ------- - --- - - ----- ---------------- ------- ----------- - ------------- - -------- -------------- - - -------- ------- -------- -------- --------------------- --------- -- ------------- - ----------------------------- ------------- - ---------- - ------------------- - ------------------------------------------------- ------- -- - ------------- - ---------- ----------------------- - --- ------------------------ ------------- ----- -- ------------------- - ----- ------------ - ------------------------------ -- --- --- ---- -------- -- ------------- - ------------------------ --------------------- ---------------- - - --- ---------------------------------------- ------- -- - ----- ---- - ------------------- ----- -------- - ----------------------- -- ------ --- ------ -- -------------- --- ----- - ------- - ------------- - ----- ---------------------- ----------------------------- - ------- - --------- -- ---- --- - --------------- - --------------------------------------------------------- -- - -- - ----------------------------- --- -- -- --------------------------------- --- -- - - -------------------- - --- - ---- - -------------------- - ------- - --- - - ------------------------------------------ ------------------ -------------------------------------- -------------- ------------------------------------------ ------------------ --------- ------- ------ --------------------------------------- ------------------------------- --------------------------------------- ------ ----------- ----------------------------- -------- -------- --------------- - ----- ---------------- - -------------------------------------------- ----- ------------ - ---------------------------------------- ----- ---------------- - -------------------------------------------- -- -------------------------- --- ---------- - --------------------------------- - ---- -- ---------------------- --- ---------- - ----------------------------- - ---- - --------------------------------- - - ----- ---------------- - -------------------------------------------- --------------------------------------------------- ------- -- - -------------------------- --- --------- ------- -------展开代码
在以上代码中,我们创建了三个 Custom Element:ProvinceSelector
、CitySelector
和 DistrictSelector
。
在 ProvinceSelector
中,我们实现了以下行为:
- 在元素被连接到文档流时,向远程获取省份数据,并添加到
select
元素中。 - 在
select
元素变化时,派发provincechange
、districtchange
和citychange
事件,通知其余选择器更新状态。 - 在
search()
方法中,搜索选项并根据用户输入过滤选项。
在 CitySelector
中,我们实现了以下行为:
- 在元素被连接到文档流时,监听父元素的
provincechange
事件,并根据所选省份从远程获取对应城市数据,并添加到select
元素中。 - 在
select
元素变化时,派发districtchange
和citychange
事件,通知其余选择器更新状态。 - 在
search()
方法中,搜索选项并根据用户输入过滤选项。
在 DistrictSelector
中,我们实现了以下行为:
- 在元素被连接到文档流时,监听父元素的
citychange
事件,并根据所选城市从远程获取对应区数据,并添加到select
元素中。 - 在
select
元素变化时,派发districtchange
事件,通知其余选择器更新状态。 - 在
search()
方法中,搜索选项并根据用户输入过滤选项。
在 HTML 中,我们使用 customElements.define()
注册这些 Custom Element,并在 search()
方法中监听用户的输入事件,并依次搜索对应的选项。
在演示中,我们让 DistrictSelector
派发 districtchange
事件,并在控制台输出选项。你可以在此基础上进行更多的扩展,比如在最后添加一个确认按钮,让用户在选择完毕后提交数据。
通过这个 Demo,你可以学习到如何使用 Custom Elements 实现深度联动的省市区选择器及基于用户输入的搜索功能。如果您还有其他关于前端类的问题,欢迎在评论区留言,我们会尽快回复您。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c7e290cc0f7239cdfe5c79