公司上一期项目中新增了省市区滑动三级联动效果,用的是mint-ui的picker组件和popup组件,效果如下:点击确定换地区,点击取消不变
省市区数据是后台给的(根据上一级的id,获取下一级数据列表,省列表传0),数据格式如下
接下来就直接上代码了
引入组件后的html部分
<mt-pop v-model="popupVisible" position="bottom" class="prop-tk">
<div class="clR pop-btn clearfix">
<p @click="cancle">取消</p>
<p @click="sureMap">确定</p>
</div>
<mt-picker ref="pickCom" :slots="slots" @change="onValuesChange" value-key="areaName"></mt-picker>
</mt-pop>
data里的slots数据和mint-ui格式一样
slots:[
{
flex: 1,
defaultIndex: 0,
values:[],
className: 'slot1',
textAlign: 'center',
}, {
pider: true,
content: '-',
// className: 'slot2'
}, {
flex: 1,
values:[],
className: 'slot3',
textAlign: 'center'
}, {
pider: true,
content: '-',
// className: 'slot4'
}, {
flex: 1,
values: [],
className: 'slot5',
textAlign: 'center'
}
],
页面加载时获取省市区数据(默认省和市是上个页面带过来的)
this.$nextTick(() => {
// 获取省数据
_this.getPrevenceData(0).then(res=>{
_this.slots[0].values = res;
// 根据默认省获取要显示的省
res.forEach((item,index)=>{
// 上个页面传过来的省
if(item.areaName == _this.mrProvience){
_this.mrpId = item.id;
_this.slots[0].defaultIndex= index;
// 获取市数据
var cityList = _this.getPrevenceData(item.id);
// 根据默认市获取要显示的市
cityList.then(rescity =>{
// 给数据做缓存取消时用
_this.oldCityList =rescity;
_this.slots[2].values = rescity;
rescity.forEach((item,index)=>{
if(item.areaName == _this.showCity){
// 缓存id如果滑动时id变化才发请求
_this.mrcid = item.id;
_this.slots[2].defaultIndex= index;
// 获取区的数据
var quList = _this.getPrevenceData(item.id);
quList.then(resqu =>{
_this.oldQuList = resqu;
_this.slots[4].values = resqu;
_this.cityDataReady = true;
var valueArr = this.$refs.pickCom.getValues()
this.oldSlots = valueArr.concat();
})
}
})
})
}
})
})
城市滑动变化触发picker组件的change事件(id变化才发对应请求,否则会多次发请求)
onValuesChange(picker,values){
//判断如果省的id变化了,就去请求市和区,否则只请求区
if(this.cityDataReady){
//当省变化的时候,请求市和区
if(this.mrpId != values[0].id){
//请求市
this.getPrevenceData(values[0].id).then(res =>{
picker.setSlotValues(2,res);
this.mrpId = values[0].id;
this.mrcid = values[2].id;
})
}
//当市变化的时候,请求区
if(this.mrcid !=values[2].id){
//请求区,当仅仅是区变化的时候,不需要发任何请求
this.getPrevenceData(values[2].id).then(res =>{
picker.setSlotValues(4,res);
this.mrpId = values[0].id;
this.mrcid = values[2].id;
})
}
} },
点击确定缓存当前数据
sureMap(){
this.popupVisible = false;
// 获取变换后的城市数据
var valueArr = this.$refs.pickCom.getValues()
this.oldSlots = valueArr.concat();
this.oldCityList = this.$refs.pickCom.getSlotValues(2);
this.oldQuList = this.$refs.pickCom.getSlotValues(4)
},
点击取消时把缓存的数据赋值给picker组件
cancle(){
_this.popupVisible = false;
// 把缓存的数据赋值给对应的slot
_this.$refs.pickCom.setSlotValues(2,_this.oldCityList);
_this.$refs.pickCom.setSlotValues(4,_this.oldQuList);
_this.$refs.pickCom.setValues(this.oldSlots);
}
在做这个功能时出现的问题主要有2个,一个是change时多发请求问题,第二个就是取消时还要回到原来的数据(因为组件默认change之后自动就变了)
还好后来问题都解决了