撸个微信小程序的省市区选择器
起因
微信小程序虽然已经有现成的封装好的省市区选择器给开发者使用,然鹅不幸的是,微信地址库的数据和公司用的地址库数据很难一一对上,那就只能撸起袖子自己写个组件了。
最终效果
文章图片
最终效果 思维导图
文章图片
思维导图 主要代码
组件 region-picker.js
/* region-picker.js */
import area from '本地 json 数据';
Component({
properties: {
showRegion: {
type: Boolean,
observer: function(newVal, oldVal) {
this.setData({
dialog: newVal,
});
},
},
regionValue: {
type: Array,
value: [],
observer: function(newVal, oldVal) {
if (newVal.length > 0) {
let select = -1;
for (let i = newVal.length - 1;
i >= 0;
i--) {
if (newVal[i].id !== '') {
select = i;
break;
}
}
// 除最低级别区(select = 2)以外,需要获取当前级别下一级的数据
this.setData({
['region.tabs']: newVal,
['region.select']: select < 2 ? select+1 : select,
}, () => {
this.setData({
area: this.getChildArea(select < 2 ? select+1 : select),
});
});
}
},
},
},
data: {
dialog: false,
area: area,
region: {
tabs: [
{
name: '请选择',
id: '',
},
{
name: '请选择',
id: '',
},
{
name: '请选择',
id: '',
},
],
select: 0,
},
},
methods: {
// 关闭 picker 触发的方法
emitHideRegion: function() {
if (this.data.region.tabs[2].id === '') {
wx.showToast({
title: '请选择所在地',
icon: 'none',
duration: 2000,
});
return false;
}
let myEventDetail = {};
// detail对象,提供给事件监听函数
let myEventOption = {};
// 触发事件的选项
this.setData({
dialog: !this.data.dialog,
});
myEventDetail = {
showRegion: this.data.dialog,
regionValue: this.data.region.tabs,
};
this.triggerEvent('myevent', myEventDetail, myEventOption);
},
bindRegionChange: function(e) {
// 获取当前选中项的name和id并赋值给data中的数据
let id ='region.tabs[' + this.data.region.select + '].id';
let name ='region.tabs[' + this.data.region.select + '].name';
this.setData({
[id]: e.target.dataset.id,
[name]: e.target.dataset.name,
});
// 除了三级以外的需要获取对应子选项
if (this.data.region.select < 2) {
this.setData({
['region.select']: ++this.data.region.select,
}, () => {
// 获取子选项
this.setData({
area: this.getChildArea(this.data.region.select),
});
});
} else {
// 三级选项选择完毕关闭省市区选择器
this.emitHideRegion();
}
},
getChildArea: function(level) {
let _id = '';
// 默认取完整的数据
let _area = area;
// 根据层级取当前层级下的数据
for (let i = 0;
i < level;
i++) {
_id = this.data.region.tabs[i].id;
for (let j = 0;
j < _area.length;
j++) {
if (_area[j].id === _id) {
_area = _area[j]._child;
break;
}
}
}
return _area;
},
// 省市区tab切换
changeRegionLevel: function(e) {
let level = e.target.dataset.level;
// 三级选项的tab点击无效果
if (level === 2) return false;
// 当前选中tab和级别小于当前选中tab的状态都置为初始化状态
for (let i = level;
i < 3;
i++) {
let string = 'region.tabs['+ i +']';
this.setData({
[string]: {
name: '请选择',
id: '',
},
});
}
this.setData({
['region.select']: level,
});
this.setData({
area: this.getChildArea(level),
});
},
},
});
组件 region-picker.wxml
/* region-picker.wxml */
选择所在地区
{{item.name}}
{{item.name}}
组件 region-picker.wxss
/* region-picker.wxss */
.free-dialog__mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
background: rgba(0, 0, 0, 0.7);
display: none;
}
.free-dialog__container {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background: #F1F1F1;
transform: translateY(150%);
transition: all 0.4s ease;
z-index: 11;
}
.free-dialog--show .free-dialog__container {
transform: translateY(0);
}
.free-dialog--show .free-dialog__mask {
display: block;
}
.free-dialog__container__header {
padding: 24rpx 30rpx;
text-align: center;
background: white;
}
.free-dialog__container__header .close {
position:absolute;
right:30rpx;
top:31rpx;
width:36rpx;
height:36rpx;
}
.free-content {
background: white;
border-bottom: 40rpx solid white;
}
.free-content.ipx {
border-bottom: 72rpx solid white;
}
.free-content__tabs__tab {
display: inline-block;
padding: 12rpx 46rpx;
font-size: 32rpx;
color: #333;
border-bottom: 4rpx solid white;
}
.free-content__tabs__tab.select {
border-color: #FA263C;
}
.free-content__scroll {
padding: 0 40rpx;
height: 480rpx;
box-sizing: border-box;
}
.free-content__scroll__item {
margin-top: 40rpx;
height: 40rpx;
line-height: 40rpx;
font-size: 28rpx;
color: #333;
}
页面的 WXML
/* 页面的 WXML */
请选择
{{regionValue[0].name}}
{{regionValue[1].name}}
{{regionValue[2].name}}
...
页面的 js
/* 页面的 js */
Page({
data: {
regionValue: [],
showRegion: false,
},
chooseRegion: function() {
this.setData({
showRegion: true,
});
},
emitHideRegion: function(e) {
this.setData({
showRegion: e.detail.showRegion,
regionValue: e.detail.regionValue,
});
},
});
总结
需要注意下的是,最低级别区级别是个特殊的临界点,因为区后面没有更低级别,所以不需要获取下一级别的数据,也不能触发 tab 事件。
然后父组件传递子自组件的值,如果后期父组件变更了这个值,子组件可以在响应函数 observer 里监听到值的变化。
我本次使用的本地省市区 JSON 数据格式为:
/* area.js */
module.exports = [{
id: '...',
name: '...',
_child: [{
id: '...',
name: '...',
_child: [{
id: '...',
name: '...'
}, ...]
}, ...]
}, ...]
【撸个微信小程序的省市区选择器】写的不是特别好,也希望能帮助到有需要的人吧,有疑问戳微信小程序官方文档,没有什么比官方文档更靠谱的了!
推荐阅读
- 一个小故事,我的思考。
- 家乡的那条小河
- 一个人的碎碎念
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- 昨夜小楼听风
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- 2019.4.18感恩日记
- 那件我们忽略的小事叫感恩
- 你有婚内虐待行为吗()