准备工作
省市区三级联动所需文件:评论回复区
文件说明:
整个文件为一个大的对象(非数组类型)
其中对象的属性名 100000 中包含所有省份,它也是一个对象格式的;
对象名为100000的每个属性中的属性名都为数字类型(其实是该地区的行政代码)。数字属性名对应的属性值是该地区的名称,同时也可以通过该属性名访问到它下级的市列表。
eg:
import districts from './js/districts.js'console.log(districts[100000])
比如当我们想获取到行政代码130000河北省下面的市级列表时:
import districts from './js/districts.js'console.log(districts[130000])
然后当我们想获得行政代码130100石家庄市下的区级列表时:
import districts from './js/districts.js'console.log(districts[130100])
没错,省市中的每一个行政代码属性名都对应着它下一级(省行政代码对应市列表,市行政代码对应区列表)的对象列表。不存在数组对象嵌套。及其简单方便。
创建 option 标签简便API
new Option('innerText', 'value属性对应的值')
类似于传统写法:
let option_1 = document.createElement('option')
option_1.text = 'innerText'
option_1.value = 'value属性对应的值'
嗯,没什么区别,但是第一种简单很多:
清空 select标签中的option标签极简方法:
selectDOM.options.length = 0
.html文件中使用模块化
将 script 标签改为 type 属性改为 module
创建三个 select标签,分别用来存放 省级列表,市级列表,区级列表,并定义好变量:
HTML:
JS:
// 获取省市区selectDOM节点let oProvince = document.getElementById('province')let oCity = document.getElementById('city')let oArea = document.getElementById('area')
定义一个特定对应,用户将用户选中的结果获取到:
let data = {province: {},city: {},area: {}}
第一步,渲染省份列表
1,引入省市区文件 import districts from './js/districts.js'
直接一个for in 循环 districts[100000] 即可;
然后在循环中创建option标签,并插入到省级select节点中:
let provinceList = districts[100000] for (let province in provinceList) {oProvince.options.add( new Option(provinceList[province], province) )}
效果:
这样我们的第一个select标签就完成了
第二步,渲染市级列表
ps: 市级列表市基于省级之后才开始渲染的,所以应该在省级select改变之后触发(onchange事件)
1,首先拿到用户选中的是第几个option;
通过selectDOM的selectedIndex可拿到对应索引值:
然后通过children获取option子元素列表,之后直接拿对应索引即可!
eg: this.children[this.selectedIndex], 因为是onChange事件,this指代selectDOM。
在操作之前,可以先把用户选中的省份数据存放在我们提前定义好的data对象中的province对象中:
data.province.code = this.children[this.selectedIndex].valuedata.province.value = this.children[this.selectedIndex].text
即此时数据应为是:
在数据存完之后我们就可以着手渲染我们的市级select标签了。
1,首先不管市级select中有没有option标签,我们先给它清除一遍(因为每个省份对应的市都不一样,如果不清除则下面渲染的市级option列表中含有上一个省份的市级option列表)
oCity.options.length = 0
2,清除完成之后我们用省级行政代码(code)去获取对应的市级列表即可:
即districts['省级行政代码'] 等于对应市级列表
districts[data.province.code] // 获取用户选中的省份的市级列表
eg:
拿到该省份的对应市级列表之后,我们只需要向渲染省级列表一样渲染市级列表即可:
第三步,渲染区级列表
第三步同第二步基本完全一样,我们完全可以让它两共用一个函数:
在市级列表的onChange事件触发之后执行,
存储用户选中的市的code以及市名。
用获取到的市级code去换对应的区级列表即可(因为不存在数组对象嵌套,所以同省级code换市列表一样);
districts[data.province.code] // 获取用户选中的市级的区级列表
在渲染区级之前先清空一直区级select下的option标签列表
eg:
代码同上基本一样,除了需要注意此时我们的存值的对应是我们事先定义好的市级对应city而不是province即可。
当区级select标签onChange事件触发时
区级的 onChange 事件触发,此时我们已经不需要再给渲染新的 select 标签了(因为不是四级联动,其实都一样啦,大不了再复制一层呗)。所以我们只需要把用户选中的结果存放在我们事先定义好的 data 中的 area 区级对象即可。
这样,当用户选择完毕之后,我们就会得到一个很清晰的对象了。
至此基本完工。
完善
初步渲染完成时应该给它下级一个默认值,这样如果用户不选了不至于获取到的数据不完整:
1,渲染完省级列表时默认给它一个选中的市,并存值。
使用element.dispatchEvent().。实现onChange事件初始化触发
参考资料:https://www.jianshu.com/p/5f9027722204
此时浏览器刚刷新数据为:
源码(不含省市区文件,省市区文件将开头):