在做项目的过程中遇到需要选择城市的表单,需要使得 省市区 三级联动选择。element-ui 中有相关组件,但该组件将三者统一在同一个 select 下拉选择框,使得数据双向绑定时还需要切分数据。故考虑根据实际开发情况封装一个通用的联动下拉选择组件。
组件代码
template
<template>
<div class="city-select">
<div>
<!-- 选择省份时:更新市、区数据 -->
<select
v-model="province"
@change="
updateCity()
updateDistrict()
pushData()
"
>
<option v-for="(item, index) in list" :key="index">{{ item.name }}</option>
</select>
<select
v-model="city"
@change="
updateDistrict()
pushData()
"
>
<option v-for="(item, index) in cityList" :key="index">{{ item.name }}</option>
</select>
<select v-model="district" @change="pushData">
<option v-for="(item, index) in DistrictList" :key="index">{{ item.name }}</option>
</select>
</div>
</div>
</template>
script
// 引入省市区数据
import list from '../../../public/data/cities-code.json'
export default {
name: 'city-select',
data() {
return {
list, // 总数据
province: '北京', // 省
cityList: [], // 市数据,
city: '', // 市
DistrictList: [], // 区数据
district: '', // 区
}
},
methods: {
// 根据省的选择更新市数据
updateCity() {
this.list.forEach((item) => {
if (item.name === this.province) {
this.cityList = item.children
}
})
this.city = this.cityList[0].name
},
// 根据市的选择更新区数据
updateDistrict() {
this.cityList.forEach((item) => {
if (item.name === this.city) {
this.DistrictList = item.children
}
})
this.district = this.DistrictList ? this.DistrictList[0].name : ''
},
// 数据变化时将数据传递给调用本组件的父组件 (在省市区数据变化时均触发数据推送)
pushData() {
this.$emit('updateData', this.province, this.city, this.district)
},
},
mounted() {
// this.updateCity()
},
}
style (sass)
// 默认样式
.city-select {
select {
height: 40px;
width: 175px;
line-height: 40px;
border: 1px solid #e5e5e5;
padding: 0 10px;
margin-right: 15px;
}
}
使用方法
- 引入组件
import CitySelect from '@/components/module/CitySelect.vue'
- 使用组件
<city-select @updateData="updateData"></city-select>
- 获取数据并使用
updateData(province, city, district) {
this.receiverProvince = province
this.receiverCity = city
this.receiverDistrict = district
},
效果展示
组件特点
- 省市区联动,会自动根据上一级选择筛选对应的子级可选项
- 选择省份会自动填充默认 市、区
使用注意事项
- 导入城市数据格式要求:
[{name: '某某省', children: [...]}, {...}, ...]
- 本组件设置有默认样式,如需更改,在父组件中通过 /deep/ 样式穿透进行设置。例如
.city-select /deep/ select {......}
遇到的问题及解决方案
- 引用该组件往往需要进行双向数据绑定,但绑定的数据存在于子组件,需要使用数据的是父组件。故考虑使用 $emit 进行数据传输,在数据变化时将省市区三个数据同时传递给父组件,并在父组件接收并使用数据
省市区数据来源:
http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/
其他 ❄️
该组件已修改并上传 npm 方便使用
地址:https://www.npmjs.com/package/m-city-select