【Strelitzia项目】vue3+ts实现element-plus中选择器省市区三级联动

简介

最近在部署项目时,想要做一个收货地址的功能,但是仅凭用户自己去输入地址感觉不太规范,假设用户输入了一个假的地址改如何处理呢,所以需要做出一个比较规范的选择器来解决这个问题。但是在这个问题的过程中存在着不少疑惑,首先就是百度找不到vue3+ts的代码,而自己本身又是后端开发人员,所以在技术层面存在着不少的疑问,vue2编写代码的方式不太熟练。所以借鉴了这篇博客,首先非常感谢这篇博客给我提供的思路 参考文章

内容

1.编写js内容

首先 点击查看这个网址中的数据格式,https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.jsonopen in new window
再去需要定义好需要接受数据的对象,其中三个常量分别是province、city 、area ,接受的数据是省、市、区三级的数据,其次是定义一个接受数据的类型 AreaList,并且创建好三个数据用于存放获取到的JSON数据

import axios from 'axios';
import { onBeforeMount, ref, watch } from 'vue'

const province = ref('')
const city = ref('')
const area = ref('')

export type AreaList = {
  code: string
  level: number
  name: string
  areaList: AreaList[]
}
const provinceList = ref<AreaList[]>([])
const cityList = ref<AreaList[]>([])
const areaList = ref<AreaList[]>([])

定义好接收数据的格式之后,需要去编写组件的样式

<div style="display: flex;">
    <el-select v-model="province" clearable placeholder="Select">
      <el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.name" />
    </el-select>
    <el-select v-model="city" clearable placeholder="Select">
      <el-option v-for="item in cityList" :key="item.code" :label="item.name" :value="item.name" />
    </el-select>
    <el-select v-model="area" clearable placeholder="Select">
      <el-option v-for="item in areaList" :key="item.code" :label="item.name" :value="item.name" />
    </el-select>
  </div>

编写好三个组件之后,需要在组件加载之前获取到组件的数据,使用到onBeforeMount钩子

// 获取到JSON数据
const getprovinceList = async () => {
  const res = await axios.get<AreaList[]>(
    'https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json'
  )
  provinceList.value = res.data
  console.log(provinceList)
}
onBeforeMount(async()=>{
  getprovinceList()
})

然后就是将 province、city 、area做好监听,以便实现在点击了广东省,会出现广州市、深圳市等信息,点击某一个市,又会出现对应的区相关信息。

// 监听省份的值改变调用的函数
watch(province,(newData)=>{
  for(let item in provinceList.value){
    if(provinceList.value[item].name === province.value)
    {
      // console.log(provinceList.value[item].name)
      cityList.value = provinceList.value[item].areaList
      console.log(cityList)
    }
    
  }
})
// 监听 市 的值改变调用的函数
watch(city,(newData)=>{
  for(let item in cityList.value){
    if(cityList.value[item].name === city.value)
    {
      // console.log(provinceList.value[item].name)
      areaList.value = cityList.value[item].areaList
      console.log(areaList)
    }
    
  }
})

这就完成啦,就是如此的简单,最后附上完整的代码出来

<script lang="ts" setup>
import axios from 'axios';
import { onBeforeMount, ref, watch } from 'vue'

const province = ref('')
const city = ref('')
const area = ref('')

export type AreaList = {
  code: string
  level: number
  name: string
  areaList: AreaList[]
}
const provinceList = ref<AreaList[]>([])
const cityList = ref<AreaList[]>([])
const areaList = ref<AreaList[]>([])

// 获取到JSON数据
const getprovinceList = async () => {
  const res = await axios.get<AreaList[]>(
    'https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json'
  )
  provinceList.value = res.data
  console.log(provinceList)
}
onBeforeMount(async()=>{
  getprovinceList()
})

// 监听省份的值改变调用的函数
watch(province,(newData)=>{
  for(let item in provinceList.value){
    if(provinceList.value[item].name === province.value)
    {
      // console.log(provinceList.value[item].name)
      cityList.value = provinceList.value[item].areaList
      console.log(cityList)
    }
    
  }
})
// 监听 市 的值改变调用的函数
watch(city,(newData)=>{
  for(let item in cityList.value){
    if(cityList.value[item].name === city.value)
    {
      // console.log(provinceList.value[item].name)
      areaList.value = cityList.value[item].areaList
      console.log(areaList)
    }
    
  }
})
</script>
<template>
  <div style="display: flex;">
    <el-select v-model="province" clearable placeholder="Select">
      <el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.name" />
    </el-select>
    <el-select v-model="city" clearable placeholder="Select">
      <el-option v-for="item in cityList" :key="item.code" :label="item.name" :value="item.name" />
    </el-select>
    <el-select v-model="area" clearable placeholder="Select">
      <el-option v-for="item in areaList" :key="item.code" :label="item.name" :value="item.name" />
    </el-select>
  </div>
</template>
<style></style>

注意事项

后续在进行更改代码的时候遇到了问题,发现将上述代码中的常量更换为了对象之后发现选择器选中的数值不会展示出来了例如这样


// 原本这部分代码
const province = ref('')
const city = ref('')
const area = ref('')
const detailAddress = ref('')
// 修改为这部分的代码
// 存储收货地址的数组
let address = reactive(
  {
    id: '',
    sid: '',
    createTime: '',
    updateTime: '',
    address: '',
    province:'',
    city:'',
    area:'',
    detailArea:'',
    phone: '',
    userName: ''
  }
)
<!--使用el-select时将绑定切换为了-->
 <el-select v-model="address.province" clearable filterable placeholder="Select">
 	<el-option v-for="item in provinceList" :key="item.code" :label="item.name" :value="item.name" />
 </el-select>

此时发现绑定的值无法使用了,目前猜测是el-select只能绑定ref对象的值才可以实现动态更新