【uniapp】设置省市区联动,vue3

先上效果图

代码

<template>
  <view>
    <button @click="changeArea">弹出地址选择器</button>
    <u-picker :show="show" ref="uPicker" :columns="cityList" @confirm="cityConfirm" @change="changeHandler" @cancel="show = false"></u-picker>
  </view>
</template>
<script setup>
import cityData from '@/city.js';
import { ref, reactive } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
const ann = ref(true);
const model1 = reactive({
  userInfo: {
    name: '',
    sex: ''
  }
});
//
const show = ref(false);
const cityName = ref('请选择地区'); // 城市选择器
const areaname = ref();
const cityList = ref([]);
const cityLevel1 = ref([]);
const cityLevel2 = ref([]);
const cityLevel3 = ref([]);
onLoad(() => {
  // 城市选择器初始化
  initCityData();
});
//控制弹出层的显示和隐藏
const changeArea = () => {
  show.value = !show.value;
};
// 城市选择器
const initCityData = () => {
  // 遍历城市js
  cityData.forEach((item1, index1) => {
    let temp2 = [];
    cityLevel1.value.push(item1.provinceName);
    let temp4 = [];
    let temp3 = [];
    // 遍历市
    item1.cities.forEach((item2, index2) => {
      temp2.push(item2.cityName);
      // 遍历区
      item2.counties.forEach((item3, index3) => {
        temp3.push(item3.countyName);
      });
      temp4[index2] = temp3;
      temp3 = [];
    });
    cityLevel3.value[index1] = temp4;
    cityLevel2.value[index1] = temp2;
  });
  // 选择器默认城市
  cityList.value.push(cityLevel1.value, cityLevel2.value[0], cityLevel3.value[0][0]);
};

// 选中时执行
const changeHandler = (e) => {
  const {
    columnIndex,
    index,
    indexs,
    value,
    values,
    // 微信小程序无法将picker实例传出来,只能通过ref操作
    picker = this.$refs.uPicker
  } = e;
  if (columnIndex === 0) {
    // 选择第一列数据时
    // 设置第二列关联数据
    picker.setColumnValues(1, cityLevel2.value[index]);
    // 设置第三列关联数据
    picker.setColumnValues(2, cityLevel3.value[index][columnIndex]);
  } else if (columnIndex === 1) {
    // 选择第二列数据时
    // 设置第三列关联数据
    picker.setColumnValues(2, cityLevel3.value[indexs[0]][index]);
  }
};

// 单击确认按钮时执行
const cityConfirm = (e) => {
  // 输出数组 [省, 市, 区]
  console.log(e.value);
  areaname.value = e.value;
  cityName.value = e.value.join('-');
  // 隐藏城市选择器
  console.log(cityName.value);
  show.value = false;
};
</script>

最后是city.js文件

好的,以下是基于uniapp的城市选择器封装代码: 1. 在components文件夹下新建一个CityPicker文件夹,里面新建CityPicker.vue文件: ``` <template> <div class="city-picker"> <van-picker :columns="columns" @change="onChange" @confirm="onConfirm" @cancel="onCancel" > <template #title> <div class="city-picker-header"> <van-icon name="arrow-left" size="20" @click="onCancel" /> <span class="city-picker-title">{{title}}</span> </div> </template> </van-picker> </div> </template> <script> import { mapState } from &#39;vuex&#39;; export default { props: { title: { type: String, default: &#39;选择城市&#39; }, visible: { type: Boolean, default: false }, value: { type: Array, default() { return [null, null, null]; } } }, computed: mapState({ cityData: state => state.city.cityData }), data() { return { columns: [ { values: [] }, { values: [] }, { values: [] } ], currentProvince: &#39;&#39;, currentCity: &#39;&#39;, currentDistrict: &#39;&#39; }; }, methods: { initColumns() { const { columns } = this; const provinceList = Object.keys(this.cityData); const province = this.currentProvince || provinceList[0]; const city = this.currentCity || Object.keys(this.cityData[province])[0]; const district = this.currentDistrict || this.cityData[province][city][0]; columns[0].values = provinceList; columns[1].values = Object.keys(this.cityData[province]); columns[2].values = this.cityData[province][city]; columns.forEach(column => { column.defaultIndex = 0; }); this.currentProvince = province; this.currentCity = city; this.currentDistrict = district; }, onChange(picker, value) { const { cityData, columns } = this; const province = columns[0].values[value[0]]; const city = columns[1].values[value[1]]; const district = columns[2].values[value[2]]; if (cityData[province][city].indexOf(district) === -1) { columns[2].values = cityData[province][city]; } }, onConfirm() { this.$emit(&#39;input&#39;, [ this.currentProvince, this.currentCity, this.currentDistrict ]); this.$emit(&#39;confirm&#39;, [ this.currentProvince, this.currentCity, this.currentDistrict ]); }, onCancel() { this.$emit(&#39;cancel&#39;); } }, watch: { visible(val) { if (val) { this.initColumns(); } }, columns: { deep: true, handler(val) { const { cityData } = this; const province = val[0].values[val[0].defaultIndex]; const city = val[1].values[val[1].defaultIndex]; const district = val[2].values[val[2].defaultIndex]; if (cityData[province][city].indexOf(district) === -1) { val[2].values = cityData[province][city]; this.currentDistrict = cityData[province][city][0]; } this.currentProvince = province; this.currentCity = city; this.currentDistrict = district; } } } }; </script> <style scoped> .city-picker { height: 300px; overflow: hidden; } .city-picker-header { display: flex; justify-content: space-between; align-items: center; padding: 10px; } .city-picker-title { font-weight: bold; font-size: 16px; } </style> ``` 2. 在store文件夹下新建一个city.js文件,里面写入城市数据: ``` export default { state: { cityData: { 北京市: { 北京市: [ &#39;东城区&#39;, &#39;西城区&#39;, &#39;崇文区&#39;, &#39;宣武区&#39;, &#39;朝阳区&#39;, &#39;丰台区&#39;, &#39;石景山区&#39;, &#39;海淀区&#39;, &#39;门头沟区&#39;, &#39;房山区&#39;, &#39;通州区&#39;, &#39;顺义区&#39;, &#39;昌平区&#39;, &#39;大兴区&#39;, &#39;怀柔区&#39;, &#39;平谷区&#39;, &#39;密云县&#39;, &#39;延庆县&#39; ] }, 天津市: { 天津市: [ &#39;和平区&#39;, &#39;河东区&#39;, &#39;河西区&#39;, &#39;南开区&#39;, &#39;河北区&#39;, &#39;红桥区&#39;, &#39;塘沽区&#39;, &#39;汉沽区&#39;, &#39;大港区&#39;, &#39;东丽区&#39;, &#39;西青区&#39;, &#39;津南区&#39;, &#39;北辰区&#39;, &#39;武清区&#39;, &#39;宝坻区&#39;, &#39;宁河县&#39;, &#39;静海县&#39;, &#39;蓟县&#39; ] }, 河北省: { 石家庄市: [ &#39;长安区&#39;, &#39;桥东区&#39;, &#39;桥西区&#39;, &#39;新华区&#39;, &#39;井陉矿区&#39;, &#39;裕华区&#39;, &#39;井陉县&#39;, &#39;正定县&#39;, &#39;栾城县&#39;, &#39;行唐县&#39;, &#39;灵寿县&#39;, &#39;高邑县&#39;, &#39;深泽县&#39;, &#39;赞皇县&#39;, &#39;无极县&#39;, &#39;平山县&#39;, &#39;元氏县&#39;, &#39;赵县&#39;, &#39;辛集市&#39;, &#39;藁城市&#39;, &#39;晋州市&#39;, &#39;新乐市&#39;, &#39;鹿泉市&#39; ], 唐山市: [ &#39;路南区&#39;, &#39;路北区&#39;, &#39;古冶区&#39;, &#39;开平区&#39;, &#39;丰南区&#39;, &#39;丰润区&#39;, &#39;滦县&#39;, &#39;滦南县&#39;, &#39;乐亭县&#39;, &#39;迁西县&#39;, &#39;玉田县&#39;, &#39;唐海县&#39;, &#39;遵化市&#39;, &#39;迁安市&#39; ], 秦皇岛市: [ &#39;海港区&#39;, &#39;山海关区&#39;, &#39;北戴河区&#39;, &#39;青龙满族自治县&#39;, &#39;昌黎县&#39;, &#39;抚宁县&#39;, &#39;卢龙县&#39; ] }, 山西省: { 太原市: [ &#39;小店区&#39;, &#39;迎泽区&#39;, &#39;杏花岭区&#39;, &#39;尖草坪区&#39;, &#39;万柏林区&#39;, &#39;晋源区&#39;, &#39;清徐县&#39;, &#39;阳曲县&#39;, &#39;娄烦县&#39;, &#39;古交市&#39; ], 大同市: [ &#39;城区&#39;, &#39;矿区&#39;, &#39;南郊区&#39;, &#39;新荣区&#39;, &#39;阳高县&#39;, &#39;天镇县&#39;, &#39;广灵县&#39;, &#39;灵丘县&#39;, &#39;浑源县&#39;, &#39;左云县&#39;, &#39;大同县&#39; ], 阳泉市: [&#39;城区&#39;, &#39;矿区&#39;, &#39;郊区&#39;, &#39;平定县&#39;, &#39;盂县&#39;] } } } }; ``` 3. 在pages文件夹下新建一个Index.vue文件,在里面调用CityPicker组件: ``` <template> <div class="container"> <van-field v-model="value" label="城市" placeholder="请选择城市" readonly @click="showPicker" /> <city-picker :visible.sync="show" :value.sync="value" @confirm="onConfirm" @cancel="onCancel" /> </div> </template> <script> import CityPicker from &#39;@/components/CityPicker/CityPicker&#39;; export default { components: { CityPicker }, data() { return { show: false, value: [null, null, null] }; }, methods: { showPicker() { this.show = true; }, onConfirm(value) { this.value = value; this.show = false; }, onCancel() { this.show = false; } } }; </script> <style scoped> .container { padding: 20px; } </style> ``` 这样一个封装好的城市选择器组件就完成了。可以根据自己的需要进行样式和功能的调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值