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

起因

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

最终效果

最终效果

思维导图

思维导图

主要代码

组件 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><imagesrc="自行替换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"><viewclass="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"><viewclass="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-pickerregion-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: '...'}, ...]}, ...]
}, ...]

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367211.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python之路_day6

本节内容&#xff1a;面向对象编程介绍为什么要用面向对象进行开发&#xff1f;面向对象的特性&#xff1a;封装、继承、多态类、方法、引子 你现在是一家游戏公司的开发人员&#xff0c;现在需要你开发一款叫做<人狗大战>的游戏&#xff0c;你就思考呀&#xff0c;人狗作…

MUI调用原生自定义方法实现计算缓存与清空缓存

由于项目需要最近在做webapp开发用的是MUI框架&#xff0c;自己本来是做原生开发的&#xff0c;在开发的时候有一个需求是实现计算缓存和清除缓存的功能&#xff0c;原生java方法实现轻轻松松&#xff0c;网上代码一大把&#xff0c;不过是webapp倒是不好搞&#xff0c;MUI自己…

Java中的多重继承与组合vs继承

有时我写了几篇有关Java 继承 &#xff0c; 接口和组成的文章。 在这篇文章中&#xff0c;我们将研究多重继承&#xff0c;然后学习组成优于继承的好处。 Java中的多重继承 多重继承是创建具有多个超类的单个类的能力。 与其他一些流行的面向对象的编程语言&#xff08;例如C …

开源|蚂蚁金服开源AntV F2:一个专注于移动,开箱即用的可视

小蚂蚁说&#xff1a;AntV 是蚂蚁金服全新一代数据可视化解决方案&#xff0c;主要子产品包括 G2、G6、F2。此前我们已经相继发布过AntV的相关开源消息与版本迭代&#xff0c;包括《蚂蚁金服开源&#xff1a;数据驱动的高交互可视化图形语法G2》&#xff0c;《开源 | 蚂蚁金服开…

Puppeteer入门初探

本文来自网易云社区作者&#xff1a;唐钊最近在看 node 爬虫相关的一些东西&#xff0c;我记得还是很久以前常用的 node 爬虫工具还是 superagengtcherrio,他们的思路是通过发起 http 请求然后截取 respone 的内容&#xff0c;但是随着前端mvvm等框架的盛行&#xff0c;现在更多…

访问量大如何增加服务器,服务器流量过大原因及解决方法

造成网站服务器流量过大的原因&#xff1a;1.网站规模较大(比如门户网站、网络商城等)&#xff0c;即网站本身访问量需求大&#xff0c;查看网站的Page View值、Hits值、日流量都很高。2.网站页面设计不合理&#xff0c;页面中包含大图片或音频、视频文件等文件&#xff0c;导致…

关于VUE项目地图开发中大量点标记绘制一些总结

问题说明 在地图开发中&#xff0c;当地图中绘制大量的标记点后&#xff0c;无论是拖动或者缩放&#xff0c;都会感觉到明显的卡顿现象。&#xff08;一般超过800个点后就比较明显了&#xff09;.在平时的工作业务中&#xff0c;由于公司的实时监控页面需要展现5000-20000车辆…

如何使用Java 5 Executor框架创建线程池

Java 5以Executor框架的形式在Java中引入了线程池&#xff0c;它允许Java程序员将任务提交与任务执行分离。 如果要使用Java进行服务器端编程&#xff0c;则线程池是维护系统可伸缩性&#xff0c;鲁棒性和稳定性的重要概念。 对于那些不熟悉Java中的线程池或这里的线程池的概念…

使用NetBeans 7.4 beta提示进行更好的基于JUnit的单元测试

在上一篇文章中 &#xff0c;我写了NetBeans 7.4 beta中提供的提示 &#xff0c;这些提示提高了开发人员避免Java异常处理带来的讨厌的运行时问题的能力。 在本文中&#xff0c;我将研究如何使用NetBeans 7.4 beta提供的另外两个提示使单元测试在执行单元测试期间更加正确和清晰…

Web 开发中 Blob 与 FileAPI 使用简述

本文节选自 Awesome CheatSheet/DOM CheatSheet&#xff0c;主要是对 DOM 操作中常见的 Blob、File API 相关概念进行简要描述。 Web 开发中 Blob 与 FileAPI 使用简述 Blob 是 JavaScript 中的对象&#xff0c;表示不可变的类文件对象&#xff0c;里面可以存储大量的二进制编…

服务器e系列和l的区别,i.e.和 e.g.的区别和使用方法

举例说明在很多文章中都有使用过&#xff0c;我想这个对大家应该并不陌生&#xff0c;但是大家知道ie和eg的区别吗&#xff0c;他们两个都是举例子的缩写词&#xff0c;但是他们之间的区别大家知道吗&#xff0c;今天我们就来介绍下这两个举例说明的缩写词到底有什么不一样。一…

通过基于JDBC的用户存储部署Identity Server

在这篇文章中&#xff0c;我将演示如何使用JDBC用户存储配置WSO2 Identity Server。 为了演示&#xff0c;我使用的是MySQL用户存储&#xff0c;但是相同的过程也适用于任何其他JDBC用户存储。 我的环境是 操作系统– Ubuntu 12.10 Java – 1.6 WSO2是4.5.0 设置MySQL数据库…

前端路由实现原理(history)

前端路由实现&#xff08;history&#xff09; 了解&#xff1a; HTML5 history新增了两个API:history.pushState和history.replaceState 两个api都接受三个参数 状态对象&#xff08;state object&#xff09;&#xff1a;一个JavaScript对象&#xff0c;与用pushState()方法…

unity 删除服务器项目,在吗?有个支持批量构建项目的好东西推荐给你

Unity Build Server是一种全新的项目构建辅助工具&#xff0c;它可以指定硬件设备&#xff0c;专门用于构建项目版本&#xff0c;帮助工作室大规模构建项目&#xff0c;提高团队生产力。很多人在选择Unity时并不会首先考虑到项目构建问题&#xff0c;而随着项目变得更大、更复杂…

使用WSO2 ESB构建制造服务总线(MSB)

在开始讨论本主题之前&#xff0c;我想介绍一些制造业中常用的术语。 术语制造执行系统&#xff08;MES&#xff09;由AMR Research于1990年提出&#xff0c;从先进的制造计算机信息系统的发展&#xff0c;MES概念已经发展了近三十年。 以下是制造执行系统协会&#xff08;MES…

mysql jion 实现原理_MySQL-join的实现原理、优化及NLJ算法

案例分析&#xff1a;selectc.*fromhotel_info_original cleft joinhotel_info_collection honc.hotel_typeh.hotel_typeandc.hotel_idh.hotel_idwhereh.hotel_idis null这个sql是用来查询出 c 表中有 h 表中无的记录&#xff0c;所以想到了用 left join 的特性(返回左边全部记…

python笔记30-docstring注释添加变量

前言 python里面添加字符串注释非常简单&#xff0c;如何将变量放入 python 的函数注释里面呢&#xff1f; docstring也就是给代码加注释的内容了&#xff0c;python可以给函数&#xff0c;类、方法&#xff0c;模块添加注释内容&#xff0c;注释标准格式一般是三个双引号&…

无线路由器在手机上如何连接服务器,192.168.10.1路由器手机怎么设置? | 192路由网...

问&#xff1a;192.168.10.1路由器手机怎么设置&#xff1f;答&#xff1a;192.168.10.1是一个C类的私有IP地址&#xff0c;目前国产的路由器中&#xff0c;睿因路由器使用192.168.10.1作为默认登录地址。鉴于此&#xff0c;下面鸿哥使用睿因路由器来进行演示介绍。温馨提示&am…

Java Mission Control 5.2终于来了! 欢迎7u40!

自从我们上次听说这个叫做任务控制的小东西已经有一段时间了。 它从JRockit一直到现在都被重命名为Java Mission Control。 这是从HotSpot和JRockit融合战略中幸存下来的部分之一。 使用今天的Java SE 7 Update 40&#xff0c;您实际上可以再次使用它。 Java Mission Control …

webview布局适配实践

一、相关概念 1、viewport&#xff1a;移动设备&#xff08;包括webview&#xff09;用来显示网页的那一块区域&#xff1b; 2、devicePixelRatio属性(别名像素比&#xff0c;简称dpr)&#xff1a;window.devicePixelRatio 物理像素 / 独立像素(css中的px)&#xff1b; 3、rem…