PS:找了很多地方,没找到适用三端小程序的省市区级联选择器的,所以自己写了一个,放这里大家需要可以拿去改改用
- ✔️ 微信
- ✔️ 支付宝小程序
- ✔️ h5
uniapp-vue2 , lodash
效果
使用:
<my-address-picker
:visible.sync="addressPicker_visible"
:activated="['广东省','深圳市','南山区']"
@confirm="addressChange"
/>
代码如下:
地址可以先用这个数据,然后按需二开,raw.githubusercontent.com/tengyuanOas…
// my-address-picker.vue
<template>
<view class="address-picker-popup">
<uni-popup
mask-background-color="rgba(0, 0, 0, .8)"
ref="detailPop"
type="bottom"
background-color="#fff"
>
<scroll-view class="popup popup-content" scroll-y>
<view class="popup-header">
<view class="font-16 font-bold pop-title">选择地址</view>
<view class="pop-close" @click="close" />
</view>
<view class="font-14 popup-main">
<picker-view :value="activeIndex" @change="bindChange" class="picker-view">
<picker-view-column class="picker-view-column">
<view class="picker-view-item" v-for="(item, index) in provinceList" :key="index">
{{ item.label }}
</view>
</picker-view-column>
<picker-view-column class="picker-view-column">
<view class="picker-view-item" v-for="(item, index) in cityList" :key="index">
{{ item.label }}
</view>
</picker-view-column>
<picker-view-column class="picker-view-column">
<view class="picker-view-item" v-for="(item, index) in countyList" :key="index">
{{ item.label }}
</view>
</picker-view-column>
</picker-view>
<view class="footer">
<view class="footer-item" @click="reset">清空</view>
<view class="footer-item" @click="confirm">确定</view>
</view>
</view>
</scroll-view>
</uni-popup>
</view>
</template>
<script>
import { getSysConstant } from '@/api';
import find from 'lodash/find';
const app = getApp();
export default {
label: 'DetailPopup',
components: {},
props: {
visible: {
required: true,
default: false
},
activated: {
required: true,
type: Array,
default: () => []
}
},
watch: {
visible(newVal) {
if (newVal) {
this.init();
this.$refs.detailPop.open();
} else {
this.$refs.detailPop.close();
}
}
},
computed: {
cityList() {
return this.provinceInfo?.children ?? [];
},
countyList() {
return this.cityInfo?.children ?? [];
}
},
data() {
return {
activeIndex: [0, 0, 0],
addressData: [],
provinceInfo: {},
cityInfo: {},
countyInfo: {},
provinceList: []
};
},
created() {
this.loadAddressInfo();
},
methods: {
async loadAddressInfo() {
// 获取级联地址数据
this.provinceList = [];
},
init(list = this.provinceList) {
if (this.activated?.length < 3) {
this.activeIndex = [0, 0, 0];
this.provinceInfo = list[0];
this.cityInfo = list[0]?.children[0] ?? {};
this.countyInfo = list[0]?.children[0]?.children[0] ?? {};
return;
}
let p_idx=0,c_idx=0,a_idx=0;
const [province = '', city = '', county = ''] = this.activated;
const provinceInfo = find(list, (info, index) => {
const bol = info.label === province;
if (bol) p_idx = index;
return bol;
});
const cityInfo = find(provinceInfo?.children, (info, index) => {
const bol = info.label === city;
if (bol) c_idx = index;
return bol;
});
const countyInfo = find(cityInfo?.children, (info, index) => {
const bol = info.label === county;
if (bol) a_idx = index;
return bol;
});
this.provinceInfo = provinceInfo;
this.cityInfo = cityInfo;
this.countyInfo = countyInfo;
this.activeIndex = [p_idx, c_idx, a_idx];
},
bindChange(e) {
const p_idx = e.detail.value[0];
const current_province = this.provinceList[p_idx];
let c_idx = e.detail.value[1];
let a_idx = e.detail.value[2];
if (this.provinceInfo.label !== current_province.label) {
c_idx = 0;
a_idx = 0;
}
const current_cityList = current_province?.children ?? [];
const current_cityInfo = current_cityList[c_idx] ?? {};
if (current_cityInfo.label !== this.cityInfo.label) {
a_idx = 0;
}
const current_countyList = current_cityInfo?.children ?? [];
const current_countyInfo = current_countyList[a_idx] ?? {};
this.provinceInfo = current_province;
this.cityInfo = current_cityInfo;
this.countyInfo = current_countyInfo;
this.activeIndex = [p_idx, c_idx, a_idx];
},
close() {
this.$emit('update:visible', false);
},
reset() {
const params = {
detail: {
value: [0, 0, 0]
}
};
this.bindChange(params);
},
confirm() {
const result = {
province: this.provinceInfo?.label,
city: this.cityInfo?.label,
county: this.countyInfo?.label
};
uni.showToast({
title: '已选地址:' + JSON.stringify(result)
});
// this.$emit('confirm', result);
// this.close();
},
}
};
</script>
<style scoped lang="scss">
.picker-view {
width: 100%;
height: 500rpx;
display: flex;
justify-content: space-between;
.picker-view-column {
width: 200rpx;
margin: 0 20rpx;
.picker-view-item {
width: 100%;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.footer {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 40rpx 80rpx 20rpx;
border-top: 1px solid rgba($color: #ddd, $alpha: 0.5);
.footer-item {
font-size: 28rpx;
}
}
</style>