微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

撸个微信小程序的省市区选择器

微信小程序虽然已经有现成的封装好的省市区选择器给开发者使用,然鹅不幸的是,微信地址库的数据和公司用的地址库数据很难一一对上,那就只能撸起袖子自己写个组件了。

最终效果

思维导图

主要代码

组件 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: [],51); font-weight: 700;">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 < 1 : select),});
          });
        }
      },data: {
    dialog: false,area: area,region: {
      tabs: [
        {
          name: '请选择',id: '',{
          name: 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: !data.dialog,});
      myEventDetail = {
        showRegion: data.region.tabs,};
      this.triggerEvent('myevent',myEventDetail,myEventOption);
    },bindRegionChange: function(e) {
      // 获取当前选中项的name和id并赋值给data中的数据
      let id ='region.tabs[' + data.region.select + '].id';
      let name ='].name';
      this.setData({
        [id]: e.target.dataset.id,[name]: e.target.dataset.name,});
      // 除了三级以外的需要获取对应子选项
      data.region.select < 2) {
        this.setData({
          ['region.select']: ++data.region.select,() => {
          // 获取子选项
          this.setData({
            area: this.getChildArea(data.region.select),});
        });
      } else {
        // 三级选项选择完毕关闭省市区选择器
        this.emitHideRegion();
      }
    },getChildArea: function(level) {
      let _id = '';
      // 认取完整的数据
      let _area = area;
      // 根据层级取当前层级下的数据
      for (let i = 0; i < level; i++) {
        _id = 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) false;
      // 当前选中tab和级别小于当前选中tab的状态都置为初始化状态
      for (let i = level; i < 3; i++) {
        let string = 'region.tabs['+ i +']';
        this.setData({
          [string]: {
            name: 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' : ''}}">
    <"free-dialog__mask" bindtap="emitHideRegion"></view>
    <"free-dialog__container">
        <"free-dialog__container__header">
            <view>选择所在地区</view>
            <image
                src="自行替换36rpx*36rpx的x图标"
                class="close"
                bindtap="emitHideRegion">
            </image>
        </view>
        <"free-dialog__container__content">
            <"free-content {{isIphoneX ? 'ipx' : ''}}">
                <"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=}"
                        bindtap="changeRegionLevel">
                        {{item.name}}
                    </view>
                </view>
                <scroll-view scroll-y class="free-content__scroll">
                    <"free-content__scroll__item"
                        wx:for={{area}"id"
                        data-id={{item.id}}"
                        data-name={{item.name}"bindRegionChange">
                        @H_46_404@scroll-view>
            </view>
        </view>
    </view>
</view>
复制代码

组件 region-picker.wxss

页面的 WXML

/* 页面的 WXML */
<view bindtap="chooseRegion">请选择</view>
<text wx:if={{regionValue[0].id}}">{{regionValue[0].name}}</text>
    <{{regionValue[1].id}{{regionValue[1].name}}</{{regionValue[2].id}{{regionValue[2].name}}</text>
</view>
...
<region-picker
    region-value={{regionValue}}"
    show-region={{showRegion}}"
    bind:myevent="emitHideRegion">
</region-picker>
复制代码

页面的 js

总结

需要注意下的是,最低级别区级别是个特殊的临界点,因为区后面没有更低级别,所以不需要获取下一级别的数据,也不能触发 tab 事件。

然后父组件传递子自组件的值,如果后期父组件变更了这个值,子组件可以在响应函数 observer 里监听到值的变化。

我本次使用的本地省市区 JSON 数据格式为:

/* area.js */
module.exports = [{
    id: '...',name: '...'
        },...]
    },...]
},...]
复制代码

写的不是特别好,也希望能帮助到有需要的人吧,有疑问戳微信小程序官方文档,没有什么比官方文档更靠谱的了!


作者: 掘金5025

原文:https://juejin.im/post/5b7520966fb9a0099744a96f

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。