在项目过程中遇到这样种需求:后台给出一个树形查询省区市的接口,一开始请求省数据,然后再选择省去动态联网加载市区数据。由于后台的数据和uview组件库中或uniapp picker组件的省市区的数据对不上,要自己重新设计,经过一番尝试,我是这样解决的。
<template>
<view class="sel-box" style="width: 100%;">
<picker mode="multiSelector" :range="multiSelector" :range-key="rangeKey" v-model="defaultSelector"
@columnchange="handleColumnChange" @change="handleChange">
<!-- disable = "true" 是禁用input 防止点击弹出键盘 -->
<input type="text" disabled="true" v-model="cityData" placeholder="请选择点位地区"
placeholder-class="placeholder" class="input-box" />
</picker>
</view>
</template>
<script>
import {
getRegionIdByPid
} from '@/api/taskSchedule.js'
export default {
name: "region-picker",
data() {
return {
multiSelector: [],
rangeKey: 'regionName',
defaultSelector: [0, 0, 0],
provinceList: [],
cityList: [],
areaList: [],
cityData: '',
};
},
mounted() {
// 初始化一
this.getRegionList(-1, '', true,() => {
this.handleColumnChange({
detail:{
column:0,
// value:0
value: this.defaultSelector[0] //自定义省
}
})
})
// 初始化二
// this.getRegionList(0, '1',false)
// 不这样做初始化的原因是 这样请求中间一列会缺失 从而导致数据混乱 上面两种方法都可以避免这种情况的出现
// this.getRegionList(-1,'')
// this.getRegionList(0, '1')
// 再次显示组件时值不清空
this.cityData = this.$store.state.home.region
},
methods: {
getRegionList(column, id,status = true,callBack = null) {
getRegionIdByPid({
pid: id
}).then(res => {
switch (column) {
case -1:
this.provinceList = res;
break;
case 0:
this.cityList = res;
//当请求市级数据时 县区级数据跟着加载 达到联动效果
this.getRegionList(1, this.cityList[0].regionId);
break;
case 1:
this.areaList = res;
break;
default:
break;
}
// 当请求县区级数据不再增加列 固定三列
if (column < 2) {
this.multiSelector.splice(column + 1, 1, res)
}
callBack && callBack()
// 初始化二
if(!status){
this.multiSelector.splice(1, 1, this.cityList)
}
})
},
handleColumnChange(event) {
let item = {}
switch (event.detail.column) {
case 0:
item = this.provinceList[event.detail.value];
break;
case 1:
item = this.cityList[event.detail.value];
break;
case 2:
item = this.areaList[event.detail.value];
break;
default:
break;
}
// 当选择省那一列时 给市区两列重新归零
if (event.detail.column == 0) {
this.defaultSelector.splice(event.detail.column, 1, event.detail.value)
this.defaultSelector.splice(1, 1, 0)
this.defaultSelector.splice(2, 1, 0)
} else {
this.defaultSelector.splice(event.detail.column, 1, event.detail.value)
}
this.getRegionList(event.detail.column, item.regionId)
},
handleChange(info) {
let arr = []
info.detail.value.forEach((item, index) => {
arr.push(this.multiSelector[index][item].regionName)
if(index == 2) this.$emit('changeCity',this.multiSelector[2][item].regionId)
})
this.cityData = arr.join('-')
this.$store.dispatch('home/setRegion',arr.join('-'))
},
}
}
</script>
<style lang="scss" scoped>
.sel-box {
height: 60rpx;
margin: 36rpx 0;
border: 1px solid #c1c1c1;
border-radius: 8rpx;
text-align: center;
color: #333333;
font-size: 22rpx;
.input-box{
font-size: 22rpx;
color: #333333;
height: 60rpx;
line-height: 60rpx;
}
/deep/ .placeholder {
font-size: 22rpx;
color: #BFBFBF;
}
}
</style>
这里说明一下 这里用splice来设置数据看官网这里 附链接
vue注意事项
if (event.detail.column == 0) {
this.defaultSelector.splice(event.detail.column, 1, event.detail.value)
this.defaultSelector.splice(1, 1, 0)
this.defaultSelector.splice(2, 1, 0)
} else {
this.defaultSelector.splice(event.detail.column, 1, event.detail.value)
}