Vue省市区三级联动组件通过数据驱动实现:省级变化重置市、区,市级变化重置区;封装为支持v-model双向绑定的自定义组件,依赖预处理的层级映射数据源,用watch响应式更新选项并emit完整选中对象。

Vue 中实现省市区三级联动表单组件,核心是数据驱动 + 依赖更新:省级变化时重置市、区选项,市级变化时重置区选项,所有选项都从统一地区数据源(如 JSON)中筛选。推荐封装为可复用的自定义组件,支持 v-model 双向绑定和外部传入初始值。
1. 准备地区数据源
使用标准的中国省市区 JSON 数据(如 china-division 或 area-data npm 包),结构类似:
- 每个省有 code(如
110000)、name(如"北京市") - 每个市属于某省,code 前四位与省 code 一致(如
110100) - 每个区属于某市,code 前六位与市 code 一致(如
110101)
建议将数据按层级预处理成对象映射,提升查找效率:
// 示例:{ '110000': [...], '110100': [...] }
const citiesMap = {};
const areasMap = {};
2. 创建自定义组件(支持 v-model)
组件接收 modelValue(v-model 绑定值),触发 update:modelValue 事件同步选中值。内部维护三个 select 的 value:
- provinceCode:当前选中的省编码
- cityCode:当前选中的市编码(依赖 provinceCode)
- areaCode:当前选中的区编码(依赖 cityCode)
关键逻辑用 watch 实现响应式联动:
将静态 Vue 页面(index.vue)改造为动态页面(Custom.vue);稿源仅限 index.vue、其引用的 CSS 与资源路径,禁止参考仓库内其他文件。Invoke when user wants to transform a static Vue page into a dynamic data-driven page with Element UI components.
watch(() => props.modelValue, (val) => {
if (val && typeof val === 'object') {
provinceCode.value = val.province || '';
cityCode.value = val.city || '';
areaCode.value = val.area || '';
}
}, { immediate: true });
watch(provinceCode, (newP) => {
cityCode.value = '';
areaCode.value = '';
if (newP) {
cityOptions.value = citiesMap[newP] || [];
} else {
cityOptions.value = [];
areaOptions.value = [];
}
});
watch(cityCode, (newC) => {
areaCode.value = '';
if (newC) {
areaOptions.value = areasMap[newC] || [];
} else {
areaOptions.value = [];
}
});
3. 模板结构与双向绑定
使用三个 元素,分别绑定 provinceCode / cityCode / areaCode,并监听 change 事件更新对应值。最终通过 emit('update:modelValue', {...}) 向外同步完整对象:
<select v-model="provinceCode"><option value="">请选择省份</option>
<option v-for="p in provinceOptions" :key="p.code" :value="p.code">{{ p.name }}</option></select><select v-model="cityCode" :disabled="!provinceCode"><option value="">请选择城市</option>
<option v-for="c in cityOptions" :key="c.code" :value="c.code">{{ c.name }}</option></select><select v-model="areaCode" :disabled="!cityCode"><option value="">请选择区县</option>
<option v-for="a in areaOptions" :key="a.code" :value="a.code">{{ a.name }}</option></select>
每次任一值变更,都 emit 完整结构:
function syncValue() {
emit('update:modelValue', {
province: provinceCode.value,
city: cityCode.value,
area: areaCode.value
});
}
4. 使用方式(简洁清晰)
父组件直接用 v-model 绑定一个对象即可,支持初始化、重置、校验等:
<areaselect v-model="form.area"></areaselect>
// data
form: {
area: {
province: '310000', // 上海市
city: '310100', // 上海市(直辖市)
area: '310115' // 浦东新区
}
}
如需支持「仅省+市」或「允许不选区」,可在组件内加 prop 控制是否渲染第三个 select,或让 areaCode 可为空。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









