省市区联动作为基础组件在各项目中都有使用,抽空封装一下。省市区JSON文件保存在本地,组件下级数据根据上级数据联动,支持删除叶子层级数据。效果图如下:
<template>
<div class="regionselect-container">
<a-form-model
layout="inline"
:model="form"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-model-item>
<a-select
size="large"
:allowClear="!form.municipalityId && !form.districtId"
placeholder="全部省份"
v-model="form.provinceId"
@change="(value) => handleChange(value,1)"
>
<a-select-option v-for="item in provinceList" :value="item.id" :key="item.id">
{{item.name}}
</a-select-option >
</a-select>
</a-form-model-item>
<a-form-model-item v-if="level!==1">
<a-select
size="large"
:allowClear="!form.districtId"
placeholder="全部城市"
notFoundContent="暂无数据"
v-model="form.municipalityId"
@change="(value) => handleChange(value,2)"
>
<a-select-option v-for="item in municipalityList" :value="item.id" :key="item.id">
{{item.name}}
</a-select-option>
</a-select>
</a-form-model-item>
<a-form-model-item v-if="level==3">
<a-select
size="large"
allowClear
placeholder="全部地区"
notFoundContent="暂无数据"
v-model="form.districtId"
@change="(value) => handleChange(value,3)"
>
<a-select-option v-for="item in districtList" :value="item.id" :key="item.id">
{{item.name}}
</a-select-option>
</a-select>
</a-form-model-item>
</a-form-model>
</div>
</template>
<script>
import region from '@/assets/region.json'
export default {
name: 'RegionSelect',
props:{
level:{
type: Number,
default: 3 //1:省 2:省市 3:省市区
},
regionData:{
type: Object,
default:()=>{
return{
provinceId: '',
municipalityId: '',
districtId: ''
}
}
}
},
data(){
return {
region,
labelCol: { span: 4 },
wrapperCol: { span: 14 },
form:{
provinceId: '',
municipalityId: '',
districtId: ''
},
}
},
watch:{
regionData:{
handler: function(){
const { provinceId, municipalityId, districtId } = this.regionData
this.form.provinceId = provinceId == '' ? undefined : Number(provinceId)
this.form.municipalityId = municipalityId == '' ? undefined : Number(municipalityId)
this.form.districtId = districtId == '' ? undefined : Number(districtId)
},
deep: true,
immediate: true
}
},
computed:{
provinceList(){
return this.region.filter(item=>item.pid == 1)
},
municipalityList(){
if(!this.form.provinceId) return []
return this.region.filter(item=>item.pid == this.form.provinceId)
},
districtList(){
if(!this.form.municipalityId) return []
return this.region.filter(item=>item.pid == this.form.municipalityId)
}
},
methods: {
handleChange(value='',type) {
switch (type){
case 1:{
this.form.provinceId = value
this.form.municipalityId = ''
this.form.districtId = ''
break
}
case 2:{
this.form.municipalityId = value
this.form.districtId = ''
break
}
case 3:{
this.form.districtId = value
break
}
}
this.$nextTick(()=>{
this.$emit('change',this.form)
})
}
}
}
</script>
<style lang='less' scoped>
.regionselect-container{
display: flex;
align-items: center;
/deep/.ant-select{
width: 160px;
}
}
</style>
注意:如果不用form表单包裹,当存在下级数据情况下改变上级数据,下级的options以及绑定的数据都更新,但是select框的数据不会修改,强制置空源数据也无法清除,默认select框会读取缓存数据,试了好长时间,最后选择用form表单包裹。