【Vue3+Vite+TS】4.0 组件三:省市区选择组件
必备UI组件
省市区选择组件将用到以下几个组件:
Select 选择器
组件设计
修改src\router\index.ts
/*
* @Author: bobokaka
* @Date: 2021-12-19 11:26:38
* @LastEditTime: 2021-12-21 19:49:02
* @LastEditors: bobokaka
* @Description: 路由
* @FilePath: \vue3-element-ui-baseline\src\router\index.ts
*/
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '../views/Home/index.vue'
import Container from '../components/baseline/container/src/index.vue'
const routes: RouteRecordRaw[] = [
{
path: '/',
component: Container,
children: [
{
path: '/',
component: Home,
},
{
path: '/chooseIcon',
component: () => import('../views/chooseIcon/index.vue'),
},
{
path: '/chooseArea',
component: () => import('../views/chooseArea/index.vue'),
},
],
},
]
const router = createRouter({
routes,
history: createWebHistory(),
})
export default router
新建src\views\chooseArea\index.vue
<template>
<div><choose-area/></div>
</template>
<script lang='ts' setup>
import ChooseArea from '../../components/baseline/chooseArea/src/index.vue'
</script >
<style lang='scss' scoped>
</style>
为了拿到省市区的数据,进入github。
https://github.com/modood/Administrative-divisions-of-China
直接下载即可。
将该项目下\Administrative-divisions-of-China-master\dist\pca-code.json复制到项目src\components\baseline\chooseArea\lib\pca-code.json下。
可以看到其中数据结构如下:
完善src\components\baseline\chooseArea\src\index.vue
<!--
* @Author: bobokaka
* @Date: 2021-12-21 19:47:23
* @LastEditTime: 2021-12-21 23:15:27
* @LastEditors: Please set LastEditors
* @Description: 省市区选择组件
* @FilePath: \vue3-element-ui-baseline\src\components\baseline\chooseArea\src\index.vue
-->
<template>
<div>
<el-select
v-model="province"
placeholder="请选择省份"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in allAreasList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select
v-model="city"
:disabled="!province"
placeholder="请选择城市"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in selectCityList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select
v-model="area"
:disabled="!province || !city"
placeholder="请选择区域"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in selectAreaList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue'
import allAreas from '../lib/pca-code.json'
//所有数据
const allAreasList = ref(allAreas)
//下拉框选择省份的值
const province = ref<string>('')
//下拉框选择城市的值
const city = ref<string>('')
//下拉框选择区域的值
const area = ref<string>('')
//城市下拉框内容所有值
const selectCityList = computed(() => {
if (!province.value) return []
else {
let cities = allAreasList.value.find(
item => item.code === province.value
)!.children
return cities
}
})
//区域下拉框内容所有值
const selectAreaList = computed(() => {
if (!city.value) return []
else {
let areas = selectCityList.value.find(
item => item.code === city.value
)!.children
return areas
}
})
</script>
<style lang="scss" scoped></style>
但是这里会报错,computed不能去修改只读的属性。
优化,通过watch进行处理:
<script lang="ts" setup>
import { ref, watch } from 'vue'
import allAreas from '../lib/pca-code.json'
//创建一个类型接口
interface TypeAreas {
code: string
name: string
children?: Array<TypeAreas>
}
//所有数据
const allAreasList = ref(allAreas)
//下拉框选择省份的值
const province = ref<string>('')
//下拉框选择城市的值
const city = ref<string>('')
//下拉框选择区域的值
const area = ref<string>('')
//城市下拉框内容所有值
const selectCityList = ref<TypeAreas[]>([])
//区域下拉框内容所有值
const selectAreaList = ref<TypeAreas[]>([])
watch(
() => province.value,
val => {
if (val) {
let cities = allAreasList.value.find(
item => item.code === province.value
)!.children
selectCityList.value = cities
}
}
)
watch(
() => city.value,
val => {
if (val) {
let areas = selectCityList.value.find(
item => item.code === city.value
)!.children
selectAreaList.value = areas!
}
}
)
</script>
以上代码解决了报错,进一步优化:
<!--
* @Author: bobokaka
* @Date: 2021-12-21 19:47:23
* @LastEditTime: 2021-12-21 23:46:28
* @LastEditors: Please set LastEditors
* @Description: 省市区选择组件
* @FilePath: \vue3-element-ui-baseline\src\components\baseline\chooseArea\src\index.vue
-->
<template>
<div>
<el-select
clearable
v-model="province"
placeholder="请选择省份"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in allAreasList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select
clearable
v-model="city"
:disabled="!province"
placeholder="请选择城市"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in selectCityList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select
clearable
v-model="area"
:disabled="!province || !city"
placeholder="请选择区域"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in selectAreaList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import allAreas from '../lib/pca-code.json'
//创建一个类型接口
interface TypeAreas {
code: string
name: string
children?: Array<TypeAreas>
}
//所有数据
const allAreasList = ref(allAreas)
//下拉框选择省份的值
const province = ref<string>('')
//下拉框选择城市的值
const city = ref<string>('')
//下拉框选择区域的值
const area = ref<string>('')
//城市下拉框内容所有值
const selectCityList = ref<TypeAreas[]>([])
//区域下拉框内容所有值
const selectAreaList = ref<TypeAreas[]>([])
//监听选择省份
watch(
() => province.value,
val => {
if (val) {
let cities = allAreasList.value.find(
item => item.code === province.value
)!.children
selectCityList.value = cities
}
city.value = ''
area.value = ''
}
)
//监听选择城市
watch(
() => city.value,
val => {
if (val) {
let areas = selectCityList.value.find(
item => item.code === city.value
)!.children
selectAreaList.value = areas!
}
area.value = ''
}
)
</script>
<style lang="scss" scoped></style>
进一步完善:
<template>
<div>
<el-select
clearable
v-model="province"
placeholder="请选择省份"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in allAreasList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select
clearable
v-model="city"
:disabled="!province"
placeholder="请选择城市"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in selectCityList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
<el-select
clearable
v-model="area"
:disabled="!province || !city"
placeholder="请选择区域"
style="margin: 0 0.1rem"
>
<el-option
v-for="item in selectAreaList"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import allAreas from '../lib/pca-code.json'
//创建一个类型接口
export interface TypeAreas {
code: string
name: string
children?: Array<TypeAreas>
}
export interface TypeArea {
code: string
name: string
}
//所有数据
const allAreasList = ref(allAreas)
//下拉框选择省份的值
const province = ref<string>('')
//下拉框选择城市的值
const city = ref<string>('')
//下拉框选择区域的值
const area = ref<string>('')
//城市下拉框内容所有值
const selectCityList = ref<TypeAreas[]>([])
//区域下拉框内容所有值
const selectAreaList = ref<TypeAreas[]>([])
//分发事件给父组件
const emits = defineEmits('change')
//监听选择省份
watch(
() => province.value,
val => {
if (val) {
let cities = allAreasList.value.find(
item => item.code === province.value
)!.children
selectCityList.value = cities
}
city.value = ''
area.value = ''
}
)
//监听选择城市
watch(
() => city.value,
val => {
if (val) {
let areas = selectCityList.value.find(
item => item.code === city.value
)!.children!
selectAreaList.value = areas
}
area.value = ''
}
)
//监听选择区域
watch(
() => area.value,
val => {
if (val) {
//下拉框选择省份的值
let provinceData: TypeArea = {
code: province.value,
name:
province.value &&
allAreasList.value.find(
item => item.code === province.value
)!.name,
}
//下拉框选择城市的值
let cityData: TypeArea = {
code: city.value,
name:
city.value &&
selectCityList.value.find(item => item.code === city.value)!
.name,
}
//下拉框选择区域的值
let areaData: TypeArea = {
code: val,
name:
val &&
selectAreaList.value.find(item => item.code === val)!.name,
}
// console.log(provinceData, cityData, areaData)
emits('change', {
province: provinceData,
city: cityData,
area: areaData,
})
}
}
)
</script>
<style lang="scss" scoped></style>
修改src\views\chooseArea\index.vue
<template>
<div><choose-area @change="changeArea" /></div>
</template>
<script lang="ts" setup>
import ChooseArea from '../../components/baseline/chooseArea/src/index.vue'
const changeArea = (value: any) => {
console.log(value.province, value.city, value.area)
}
</script>
<style lang="scss" scoped></style>
发表评论 (审核通过后显示评论):