一、巧用watch来达到三级联动效果
1.在component文件夹下创建文件夹chooseArea,创建对应文件
2.在views下面注册组件,然后在router下面配置路由
{
path:'/chooseArea',
component:() => import('../views/chooseArea/index.vue'
},
3.从github下载所需要的省市区数据
这里使用的是省市区三级联动数据,带编码的pca-code-json文件
4.代码
<template>
<div>
<el-select clearable placeholder="请选择省份" v-model="province">
<el-option v-for="item in areas" :key="item.code" :value="item.name" :lable="item.name"></el-option>
</el-select>
<el-select clearable :disabled="!province" style="margin:0 20px" placeholder="请选择城市" v-model="city">
<el-option v-for="item in selectCity" :key="item.code" :value="item.name" :lable="item.name"></el-option>
</el-select>
<el-select clearable :disabled="!province || !city" placeholder="请选择区域" v-model="area">
<el-option v-for="item in selectArea" :key="item.code" :value="item.name" :lable="item.name"></el-option>
</el-select>
</div>
</template>
<script lang="ts" setup>
import { computed, ref,watch } from 'vue'
import allAreas from '../lib/pca-code.json'
// 下拉框选择省份的值
let province = ref<string>('')
// 下拉选择城市的值
let city = ref<string>('')
// 下拉选择区域的值
let area = ref<string>('')
// 所有的省市区数据
let areas = ref(allAreas)
// 城市下拉框所有的值
let selectCity = ref<any[]>([])
// 区域下拉框所有的值
let selectArea = ref<any>([])
// 监听选择省份
watch(()=>province.value,val =>{
if(val){
let cities = areas.value.find(item => item.name === province.value)!.children
selectCity.value = cities
}
city.value = ''
area.value = ''
})
// 监听选择城市
watch(()=>city.value,val =>{
if(val){
let area = selectCity.value.find(item => item.name === city.value)!.children
selectArea.value = area
}
area.value = ''
})
</script>
<style lang="scss" scoped>
</style>
二、完善省市区组件并给父组件分发事件
1.创建接口并导出
export interface AreaItem{
name:string,
code:string,
children?:AreaItem[]
}
export interface Data{
name:string,
code:string
}
2.分发事件给父组件
let emits = defineEmits(['change'])
3.监听选择区域
watch(()=>area.value,val => {
if(val){
let provinceData:Data ={
name:province.value,
code: province.value && allAreas.find(item => item.name === province.value)!.code
}
let cityData:Data = {
name:city.value,
code:city.value && selectCity.value.find(item => item.name === city.value)!.code
}
let areaData:Data = {
name:val,
code:val && selectArea.value.find(item => item.name === val)!.code
}
// console.log(provinceData,cityData,areaData);
emits('change',{
province:provinceData,
city:cityData,
area:areaData
})
}
})
4.在注册的父组件中,引入事件
views/chooseArea/index.vue
<template>
<div>
<m-choose-area @change="changeArea"></m-choose-area>
</div>
</template>
<script lang="ts" setup>
import mChooseArea from '../../components/chooseArea/src/index.vue';
let changeArea = (val:any) => {
console.log(val);
}
</script>
三、完整代码
components/chooseArea/src/index.vue
<!--
* @Author: error: git config user.name && git config user.email & please set dead value or install git
* @Date: 2022-06-09 14:30:50
* @LastEditors: error: git config user.name && git config user.email & please set dead value or install git
* @LastEditTime: 2022-06-09 19:04:18
* @FilePath: \mm-components\src\components\chooseArea\src\index.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div>
<el-select clearable placeholder="请选择省份" v-model="province">
<el-option v-for="item in areas" :key="item.code" :value="item.name" :lable="item.name"></el-option>
</el-select>
<el-select clearable :disabled="!province" style="margin:0 20px" placeholder="请选择城市" v-model="city">
<el-option v-for="item in selectCity" :key="item.code" :value="item.name" :lable="item.name"></el-option>
</el-select>
<el-select clearable :disabled="!province || !city" placeholder="请选择区域" v-model="area">
<el-option v-for="item in selectArea" :key="item.code" :value="item.name" :lable="item.name"></el-option>
</el-select>
</div>
</template>
<script lang="ts" setup>
import { computed, ref,watch } from 'vue'
import allAreas from '../lib/pca-code.json'
export interface AreaItem{
name:string,
code:string,
children?:AreaItem[]
}
export interface Data{
name:string,
code:string
}
// 下拉框选择省份的值
let province = ref<string>('')
// 下拉选择城市的值
let city = ref<string>('')
// 下拉选择区域的值
let area = ref<string>('')
// 所有的省市区数据
let areas = ref(allAreas)
// 城市下拉框所有的值
let selectCity = ref<AreaItem[]>([])
// 区域下拉框所有的值
let selectArea = ref<AreaItem[]>([])
// 分发事件给父组件
let emits = defineEmits(['change'])
// 监听选择省份
watch(()=>province.value,val =>{
if(val){
let cities = areas.value.find(item => item.name === province.value)!.children
selectCity.value = cities
}
city.value = ''
area.value = ''
})
// 监听选择城市
watch(()=>city.value,val =>{
if(val){
let area = selectCity.value.find(item => item.name === city.value)!.children!
selectArea.value = area
}
area.value = ''
})
// 监听选择区域
watch(()=>area.value,val => {
if(val){
let provinceData:Data ={
name:province.value,
code: province.value && allAreas.find(item => item.name === province.value)!.code
}
let cityData:Data = {
name:city.value,
code:city.value && selectCity.value.find(item => item.name === city.value)!.code
}
let areaData:Data = {
name:val,
code:val && selectArea.value.find(item => item.name === val)!.code
}
// console.log(provinceData,cityData,areaData);
emits('change',{
province:provinceData,
city:cityData,
area:areaData
})
}
})
</script>
<style lang="scss" scoped>
</style>