A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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

思维导图

主要代码
组件 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.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.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="自行替换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>复制代码
组件 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 */<view bindtap="chooseRegion">请选择</view><view>    <text wx:if="{{regionValue[0].id}}">{{regionValue[0].name}}</text>    <text wx:if="{{regionValue[1].id}}">{{regionValue[1].name}}</text>    <text wx:if="{{regionValue[2].id}}">{{regionValue[2].name}}</text></view>...<region-picker    region-value="{{regionValue}}"    show-region="{{showRegion}}"    bind:myevent="emitHideRegion"></region-picker>复制代码
页面的 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: '...'        }, ...]    }, ...]}, ...]复制代码写的不是特别好,也希望能帮助到有需要的人吧,有疑问戳微信小程序官方文档,没有什么比官方文档更靠谱的了!



链接:https://juejin.im/post/5b7520966fb9a0099744a96f



2 个回复

倒序浏览
奈斯
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马