在后台管理系统中,省市区三级联动是非常常见的需求,无论是查询条件、新增表单、编辑弹窗,都需要用到。
为了避免重复代码,提升开发效率,我们可以把省市区三级联动封装成一个通用复用组件,支持:
- 三级联动
- v-model 双向绑定
- 数据回显(编辑页面必备)
- 清空、禁用联动
- 多页面复用
之前我们用了三个下拉select来实现➡️:Vue3 + Element Plus 省市区县级联下拉select组件封装
本文以同样的实现思路,用el-cascader来一步一步实现。即:由3 个 select变为1个个 cascader
全部代码⬇️
javascript
<template>
<div class="region-picker">
<el-cascader
v-model="selectedIds"
:options="provinceList"
placeholder="请选择省/市/区"
clearable
style="width: 100%"
@change="handleChange"
/>
</div>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
// 模拟省市区数据(和你原来一样)
const regionData = [
{
value: '110000',
label: '北京市',
children: [
{
value: '110100',
label: '北京市',
children: [
{ value: '110101', label: '东城区' },
{ value: '110102', label: '西城区' },
{ value: '110105', label: '朝阳区' },
{ value: '110106', label: '丰台区' },
{ value: '110108', label: '海淀区' },
]
}
]
},
{
value: '410000',
label: '河南省',
children: [
{
value: '410100',
label: '郑州市',
children: [
{ value: '410102', label: '中原区' },
{ value: '410103', label: '二七区' },
{ value: '410104', label: '管城回族区' },
{ value: '410105', label: '金水区' },
]
},
{
value: '410300',
label: '洛阳市',
children: [
{ value: '410302', label: '老城区' },
{ value: '410303', label: '西工区' },
]
}
]
}
]
// 类型定义
interface RegionModel {
provinceId: string
cityId: string
districtId: string
}
// Props
const props = withDefaults(defineProps<{
modelValue?: RegionModel
}>(), {
modelValue: () => ({ provinceId: '', cityId: '', districtId: '' })
})
const emit = defineEmits<{
'update:modelValue': [value: RegionModel]
'change': [value: RegionModel]
}>()
// cascader 绑定值是数组 [省id, 市id, 区id]
const selectedIds = ref<string[]>([])
// 选项
const provinceList = computed(() => regionData || [])
// 外部 modelValue 同步进来(编辑回显)
watch(
() => props.modelValue,
(val) => {
if (val) {
selectedIds.value = [
val.provinceId || '',
val.cityId || '',
val.districtId || ''
].filter(Boolean)
}
},
{ deep: true, immediate: true }
)
// 内部选择变化 → 抛给父组件
const handleChange = (ids: string[]) => {
const value = {
provinceId: ids[0] || '',
cityId: ids[1] || '',
districtId: ids[2] || ''
}
emit('update:modelValue', value)
emit('change', value)
}
</script>
<style scoped>
.region-picker {
width: 100%;
}
</style>
任意页面调用⬇️
javascript
<RegionPicker v-model="form.region" />
如果需要赋默认值(如编辑弹窗)⬇️
javascript
const form = ref({
region: {
provinceId: '410000',
cityId: '410100',
districtId: '410105'
}
})
如有疑问,欢迎评论区友好讨论😊