elementUI的el-cascader实现省市区搜索
目录
elementUI的el-cascader实现省市区搜索
1. 应用场景
全国省市区级联选择器增加
搜索
地级市
和
直辖市
等城市city级别的需求。即能够
全选整个市
最终效果如下:
2.实现
template部分
<el-cascader
ref="orgRegion"
popper-class="searchFilterPopper"
:options="chinaJson"
v-model="institution.region"
:props="{ multiple: true, label: 'label', value: 'label'}"
collapse-tags
placeholder="地区"
@input.native="handleInputRegion"(核心,用以监听用户输入)
@visible-change="handleVisibleRegion($event, 'orgRegion')"
@change="handleChangeLocation('orgRegion')"
clearable
filterable(开启搜索)
>
</el-cascader>
js部分
chinaJson: [ // 类似这样树形结构的json文件
{
"value": {
"value": "110000",
"label": "北京市",
"level": "province"
},
"label": "北京市",
"level": "province",
"children": [...]
}
],
import chinaJson from '...'
data(){
return {
noDistrict: [], // 没有区县的数据
resAllProvinceCity: [], // 所有的省市
chinaJson,
institution: {
region: [], //
lastRegion: [], // 最后传给后端的地区格式 [{city: "郑州"}]
}
}
},
mounted(){
this.filterGetNoCityChildren();
},
methods:{
handleChangeLocation(refName) {
const { lastRegion, frontRegion } = this.getLastSelectRegion(refName);
if (refName === 'orgRegion') {
this.institution.lastRegion = lastRegion;
} else {
this.assets.lastRegion = lastRegion;
}
this.frontRegion = frontRegion;
},
// 获取最后的选中的省市区(暴力遍历...)
getLastSelectRegion(refName) {
// 即获取到最大级别的地区数组,如全选了北京,则返回province:'北京市',
// 如选中北京市海淀区,则返回 [{province: "北京市", city: "北京", district: "海淀区"}]
let checkedNodeList = this.$refs[refName].getCheckedNodes();
checkedNodeList = checkedNodeList.filter(item => !(item.parent && item.parent.checked));
const lastRegion = [];
const frontRegion = [];
checkedNodeList.forEach((item) => {
const { data } = item; // value
if (data.level === 'district') {
const parentData = item.parent.data;
const graphParentData = item.parent.parent.data;
lastRegion.push({
[graphParentData.level]: graphParentData.label,
[parentData.level]: parentData.label,
[data.level]: data.label,
});
} else if (data.level === 'country') {
lastRegion.push({ [data.level]: '中国' });
} else {
lastRegion.push({ [data.level]: data.label });
}
// frontRegion.push({ [data.level]: value }); // 原
frontRegion.push({ [data.level]: data.value });
});
return {
lastRegion, frontRegion
// frontRegion: [{city: {value: "130500", label: "邢台", level: "city"}}]
};
},
// 过滤掉city级别的所有children(来自菜鸟的暴力遍历.......求优化)
filterGetNoCityChildren() { // deep
const resRegion = this._.cloneDeep(this.chinaJson); // loadash
const resAllProvinceCity = [];
const noDistrict = resRegion.filter((province) => {
if (province.children && province.children.length) {
resAllProvinceCity.push(province.label);
// eslint-disable-next-line no-param-reassign
province.children = province.children.filter((city) => {
if (city.children && city.children.length) {
// eslint-disable-next-line no-param-reassign
city.children = null;
resAllProvinceCity.push(city.label);
}
return city;
});
}
return province;
});
this.noDistrict = noDistrict;
this.resAllProvinceCity = resAllProvinceCity;
},
handleInputRegion(e) { // 用户输入变化的时候修改el-cascader的数据源
this.chinaJson = this.resAllProvinceCity.includes(e.target.value) ? this.noDistrict : chinaJson;
},
handleVisibleRegion(state, refName) { // 收起的时候还原数据源,并回显数据
if (!state) {
this.chinaJson = chinaJson;
const resKey = refName === 'orgRegion' ? 'institution' : 'assets';
this[resKey].region = this.filterRegionToPage(this.getLastSelectRegion(refName).lastRegion);
}
},
// 回显省市区级联选择器 (菜鸟循环......求优化)
filterRegionToPage(region) {
if (!region || !Array.isArray(region) || !region.length) return [];
const resRegion = [];
region.forEach((item) => {
if (item.country && item.country === '中国') {
resRegion.push(['全国']);
} else if (item.province && item.city && item.district) { // 存在县区
resRegion.push(Object.values(item));
} else if (!item.province && item.city && !item.district) { // city
this.chinaJson.forEach((province) => {
if (province.children !== null) {
province.children.forEach((city) => {
if (city.label === item.city) {
city.children.forEach((district) => {
resRegion.push([province.label, city.label, district.label]);
});
}
});
}
});
} else { // province 直辖市同等
const targetProvince = this.chinaJson.filter(province => item.province && item.province.includes(province.label));
if (targetProvince.length && targetProvince[0].children !== null) {
targetProvince[0].children.forEach((city) => {
// eslint-disable-next-line no-unused-expressions
if (Array.isArray(city.children)) {
city.children.forEach((district) => {
resRegion.push([targetProvince[0].label, city.label, district.label]);
});
} else {
resRegion.push([targetProvince[0].label, city.label]);
}
});
}
}
});
return resRegion;
},
}