开开心心工作,兢兢业业生活
一、实现省市区级联选择(插件)
1. 需求:实现一个省市区的级联选择器,点击一级,动态加载下一级
那好,我们找个轮子
2. 他山之石(找个轮子)
Element UI 中国省市区级联数据
安装:
npminstall element-china-area-data -S
使用:
<template><div id="app"><el-cascader
size="large":options="options"
v-model="selectedOptions"
@change="handleChange"></el-cascader></div></template><script>import{ regionData }from'element-china-area-data'exportdefault{data(){return{options: regionData,selectedOptions:[]}},methods:{handleChange(value){
console.log(value)}}}</script>
预览:
回复:
领导: 不行,多余的包会影响加载速度,我们有自己的接口
二、实现行政区三级选择 - 自己封装
1. 需求:
请求接口,获取第一级内容(省份),点击省份项,请求数据,获取第二级内容(城市)并动态加载出来,点击城市,请求数据,动态加载第三级内容(区域)
2. 组件选择
Element UI 的 Demo:
<el-cascader:props="props"></el-cascader><script>let id =0;exportdefault{data(){return{props:{lazy:true,lazyLoad(node, resolve){const{ level }= node;setTimeout(()=>{const nodes = Array.from({length: level +1}).map(item=>({value:++id,label:`选项${id}`,leaf: level >=2}));// 通过调用resolve将子节点数据返回,通知组件数据加载完成resolve(nodes);},1000);}}};}};</script>
核心:
// 理解 level 的目的和意义const nodes = Array.from({length: level +1})
3. 话不多说(直接组件封装)
组件:
<template><divclass="cascaderArea"><el-cascader:props="props"v-model="selectedOptions"placeholder="请选择行政区域"@change="handleChange"style="width: 270px"></el-cascader></div></template><script>import{ areaOption }from'@/assets/api'exportdefault{name:'cascaderArea',data(){return{selectedOptions:[],props:{lazy:true,lazyLoad:(node, resolve)=>{const{ level }= node // node 节点数据 const nodes =[]// 动态节点let type = level ==0?"0": node.value // 0 代表第一次请求this.provinceFn(type).then((res)=>{
res.list.map((item)=>{let area ={value: item.id,label: item.areaName,leaf: node.level >=2,};
nodes.push(area)});resolve(nodes)// 回调}).catch((error)=>{
console.log(error)})},}}},methods:{provinceFn(id){// 获取省市区街道returnareaOption(id)},handleChange(value){// 选择的行政区this.$emit('getSelectedOptions', value)}}}</script><stylelang="scss"scoped></style>
父组件:
<template><CascaderArea@getSelectedOptions='getSelectedOptions'/></template><script>import CascaderArea from'@/components/cascaderArea.vue'...components:{ CascaderArea },methods:{getSelectedOptions(val){this.selectedOptions = val
}}</script>
4. 预览:
5. 反思:
这个级联选择器不仅仅可以用在省市区的级联选择上,更可以面对庞大数据,做一个多层级选择菜单,实现数据的分级渲染
三、实现行政区三级自由选择
1. 存在的问题:
- 上面这个级联选择器要求必须选定第三级,不能直接选择一级 / 二级
- 如果第三级无数据,会导致无法选择
2. 思路:
- 样式: 采用 select 来实现,进行下拉框一个个选择
- 动态显示: 监听上一个下拉框是否有内容,决定要不要显示下一个 select
- 动态加载: 获取上一个下拉框内容作为参数,请求下一个下拉框的数据,如果返回数据为空,也不显示该 select(解决第三级无数据导致无法选择的问题)
- 非空校验: 只校验第一个下拉框内容是否为空,只要第一个输入框不为空可以直接提交
- 回显: 需要后端返回行政区全名,传入第一个下拉框,获取焦点时重新选择
3. 代码实现:
HTML:
<el-form-itemlabel="行政区域地址"prop="province"class="wholeLine"><el-selectv-model="lineData.province"placeholder="请选择省份"@change="provinceSelect"><el-optionv-for="item in provinceOptions":label="item.areaName":key="item.id":value="item.id"></el-option></el-select><el-selectv-show="this.lineData.province && this.cityOptions.length != 0"v-model="lineData.regionCity"placeholder="请选择城市"@change="citySelect"><el-optionv-for="item in cityOptions":label="item.areaName":key="item.id":value="item.id"></el-option></el-select><el-selectv-show="this.lineData.regionCity && this.countyOptions.length != 0"v-model="lineData.regionCounty"placeholder="请选择县/区"@change="countySelect"><el-optionv-for="item in countyOptions":label="item.areaName":key="item.id":value="item.id"></el-option></el-select></el-form-item>
JS:
provinceSelect(val){// 省份 下拉框值改变时回调this.provinceFullName =this.getLabel(val,this.provinceOptions)if(this.lineData.regionCity){// 千万要做一层判断,直接置空会导致 mode 绑定为 空this.lineData.regionCity =''}if(this.lineData.regionCounty){this.lineData.regionCounty =''}area(val).then(res=>{this.cityOptions = res.list
})},citySelect(val){// 城市 下拉框值改变时回调this.cityFullName =this.getLabel(val,this.cityOptions)if(this.lineData.regionCounty){// 千万要做一层判断,直接置空会导致 mode 绑定为 空this.lineData.regionCounty =''}area(val).then(res=>{this.countyOptions = res.list
})},countySelect(val){// 区/县 下拉框值改变时回调this.countyFullName =this.getLabel(val,this.countyOptions)},
4. 预览:
5. 思考:
如果有更好的解决方案可以留言,感谢批评指正
- 自由选择无提示: 用户能够自由选择 一 / 二 / 三级,这点提示性不强
- 回显: 动态加载导致不能回显是通病,需要后端返回一个字段专门用于回显
- 输入框样式: 输入框的样式不够优雅,可以尝试使用
el-tree
开开心心工作,认认真真生活~
版权归原作者 后海 0_o 所有, 如有侵权,请联系我们删除。