微信小程序虽然已经有现成的封装好的省市区选择器给开发者使用,然鹅不幸的是,微信地址库的数据和公司用的地址库数据很难一一对上,那就只能撸起袖子自己写个组件了。
最终效果 思维导图 主要代码组件 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 */ <view class="free-dialog {{dialog ? 'free-dialog--show' : ''}}"> <view class="free-dialog__mask" bindtap="emitHideRegion"></view> <view class="free-dialog__container"> <view class="free-dialog__container__header"> <view>选择所在地区</view> <image src=http://www.yiyongtong.com/archives/"自行替换36rpx*36rpx的x图标" class="close" bindtap="emitHideRegion"> </image> </view> <view class="free-dialog__container__content"> <view class="free-content {{isIphoneX ? 'ipx' : ''}}"> <view class="free-content__tabs"> <view class="free-content__tabs__tab {{region.select === index ? 'select' : ''}}" wx:for="{{region.tabs}}" wx:key="{{index}}" wx:if="{{index <= region.select}}" data-level="{{index}}" bindtap="changeRegionLevel"> {{item.name}} </view> </view> <scroll-view scroll-y class="free-content__scroll"> <view class="free-content__scroll__item" wx:for="{{area}}" wx:key="id" data-id="{{item.id}}" data-name="{{item.name}}" bindtap="bindRegionChange"> {{item.name}} </view> </scroll-view> </view> </view> </view> </view> 复制代码