最近用vue做一个公众号用到了mint-ui的picker,选择地区的三级联动,由于picker无法加载动态数据,经过各种百度,最后使用promise对象,将异步转换为同步。完美解决三级联动效果,文章借助于:https://blog.csdn.net/NAMECZ/article/details/85286095
<template>
<div>
<mt-popup v-model="areaVisible" position="bottom">
<mt-picker :slots="slots" valueKey="name" showToolbar @change="selectArea">
<div class="mui-card-footer">
<a v-on:click="cancel" class="mui-card-link">取消</a>
<a v-on:click="determine" class="mui-card-link">确认</a>
</div>
</mt-picker>
</mt-popup>
</div>
</template>
<script>
export default {
data () {
return {
flag: false, // 初始时禁止picker自动加载
areaVisible: false, // 初始选择地区弹窗为关闭状态
cityName: '', // 最终选中的地区的名字
cityCode: '', // 最终选中的地区的id
slots: [ // 渲染格式必须留着
{ // 省
flex: 1,
values: ['请选择'], // 省份数组
className: 'slot1',
textAlign: 'center',
value: 14
},
{ // 分隔符
divider: true,
content: '-',
className: 'slot2'
},
{ // 市
flex: 1,
values: ['请选择'],
className: 'slot3',
textAlign: 'center'
},
{
divider: true,
content: '-',
className: 'slot4'
},
{ // 县
flex: 1,
values: ['请选择'],
className: 'slot5',
textAlign: 'center'
}
]
}
},
watch: { // 监听值变动
// 监听隐藏显示值变动
areaVisible (data) {
this.$emit('cancel', this.areaVisible) // 监听组件是否隐藏把值传给父组件
}
},
props: ['initial', 'onpid', 'oncityCode'], // initial picker显示隐藏状态,onpid 详情数据id(有则编辑),oncityCode 详情返回的省市区id
methods: {
// 选择地区
selectArea (picker, values) {
if (this.flag) { // 组件初始化默认禁止picker自动加载
this.area(values[0].id).then((data) => { // 通过一级 省的id 获取市的列表
picker.setSlotValues(1, data) // 将市的地区列表放入 slots的二级列表中
})
this.area(values[1].id).then((data) => { // 通过 二级 市的id 获取区域的列表
picker.setSlotValues(2, data) // 将区的地区列表放入 slots的三级列表中
})
var arr = picker.getValues()
// console.log(arr)
this.cityName = `${arr[0].name}-${arr[1].name}-${arr[2].name}`
this.cityCode = {
province: arr[0].id,
city: arr[1].id,
county: arr[2].id
}
}
},
// 调取地区列表的函数
area (id) {
// 所以我们这里使用promise对象,将异步转换为同步。
return new Promise((resolve, reject) => {
this.$http.get('receive/address/area/' + id).then((json) => {
if (json.body.code === 200) {
resolve(json.body.data)
}
})
})
},
// 点击确定
determine (e) {
this.areaVisible = !this.areaVisible // 关闭
this.$emit('determine', [this.cityName, this.cityCode]) // 把选中的名字以及id传给父组件
},
// 点击取消
cancel () {
this.areaVisible = !this.areaVisible
this.$emit('cancel', this.areaVisible) // 给父方法传值
},
popup () { // 父方法传值
this.areaVisible = !this.initial
this.flag = true
}
},
beforeMount () { // 默认取省级数据,不能再methods请求否则无法渲染
// 页面初始化默认取省级数据 0 默认id
this.$http.get('receive/address/area/0').then((json) => {
if (json.body.code === 200) {
this.slots[0].values = json.body.data // .map(data => data.id)
// 编辑回显 如有地址id为编辑
if (parseInt(this.onpid)) {
var index = json.body.data.findIndex(fruit => fruit.id === this.oncityCode.province) // 得到指定省id数据下标
this.slots[0].defaultIndex = index // 设置初始值下标
// 根据省拿到市数据 并设置初始值
this.area(this.oncityCode.province).then((data) => { // 通过一级 省的id 获取市的列表
var index = data.findIndex(fruit => fruit.id === this.oncityCode.city) // 得到指定市id数据下标
this.slots[2].values = data // 市数据
this.slots[2].defaultIndex = index // 设置初始值下标
})
// 根据省市到区数据 并设置初始值
this.area(this.oncityCode.city).then((data) => { // 通过二级 市的id 获取区的列表
var index = data.findIndex(fruit => fruit.id === this.oncityCode.county) // 得到指定区id数据下标
this.slots[4].values = data // 区数据
this.slots[4].defaultIndex = index // 设置初始值下标
})
}
} else {
this.$toast(json.body.message)
}
})
}
}
</script>
<style lang="scss" scoped>
.mui-card-footer{border-bottom: 1px solid #eee;}
.mint-popup-bottom{width: 100%;}
</style>