微信小程序自定义yPicker组件实现省市区三级联动功能


Posted in Javascript onOctober 29, 2020

自从上一篇文章:微信小程序自定义日历组件及flex布局最后一行对齐问题分析 出来以后,有人私聊我说能不能从头分析一下我开源的自定义组件?一直没时间。这不,最近项目中有个需求是 省市区三级联动 ,我就顺便从组件库中的第一个 「扩展日期-时间picker(点此直接至GitHub,欢迎star)」组件开始说一下这两个功能的实现。


简单说一下“自定义日期-时间组件”

它的背景是项目的第一版当时发现微信小程序内置的日期组件:picker只能精确到某一天(年月日),但是我们很多时候需要年月日时分甚至是年月日时分秒(如结束时间/发布时间)。

微信小程序自定义yPicker组件实现省市区三级联动功能

笔者仔细翻阅了官方文档和许多博主文章发现提出了各种各样的解决方案(但很遗憾没发现有博主详细公开代码),但是对于这样一个其实并不需要“联动”、列数也不固定的功能,用多列picker模拟多列选择器 即可。

<picker mode="multiSelector" bindchange="bindMultiPickerChange" bindcolumnchange="bindMultiPickerColumnChange" value="{{multiIndex}}" range="{{multiArray}}">
	<input value='{{time}}' readonly="" disabled="true" placeholder='{{defaulttext}}' />
</picker>

其中 readonly="" disabled="true" 的作用是使“input聚焦时软键盘不弹出”(两个属性作用一样,都写是因为Android和iOS的兼容性问题)。

用input代替view是因为input的placeholder方便实现“无选中时默认提示”的效果。

主要实现策略

如上所示,监听了两个事件,分别是:日期选择窗口弹出时以及点击“确定”按钮时触发函数change、多列选择器中每一列滑动时触发事件columnchange。

  • change中很简单:只需要把选中的数据暴露给页面中(或者通过 triggerEvent 返回给调用页面)即可;
  • columnchange中要做的就是当前选中的每一列的值填充到data中对应数组的某一项。比如:e.detail.column==1 时表示当前滑动的是第二列(月份),此时需要判断的是每一月有几天:
if (e.detail.column == 1) {
 let num = parseInt(this.data.multiArray[e.detail.column][e.detail.value]);
 let temp = [];
 if (num == 1 || num == 3 || num == 5 || num == 7 || num == 8 || num == 10 || num == 12) { //判断31天的月份
 for (let i = 1; i <= 31; i++) {
  if (i < 10) {
  i = "0" + i;
  }
  temp.push("" + i);
 }
 this.setData({
  ['multiArray[2]']: temp //第三列天数更新(根据月份)
 });
 }
}

注意: 多列picker组件监听两个参数:multiArray和multiIndex,他们都是数组!
multiArray主要用来表示监听几列,其元素都是一个个数组,如:[years, months, days, hours, minutes]
multiIndex是当前每一列(点开时的)初始值!如:[10, meng_date.getMonth(), meng_date.getDate()-1, meng_date.getHours(), meng_date.getMinutes()]
一般来说,multiIndex中的值也被用来当做取multiArray中元素时的第二个索引!


说说省市区三级联动实现

先将城市列表文件发出来:(永久免费下载)

链接: https://pan.baidu.com/s/1tPabuqSY6SfBNfOEMkjPVA

提取码: wc3g

使用时按如下引入即可:(是一个citysearch.js文件)

import placeArrays from 'citysearch文件路径';
const placeArray=placeArrays.placeArray

微信小程序自定义yPicker组件实现省市区三级联动功能

正式开始

不知大家有没有使用过,或听过小程序的 picker-view 组件,其定位就是:嵌入页面的滚动选择器
它有三个参数:

参数 类型 说明
value Number Array 数组中的数字依次表示 picker-view 内的 picker-view-colume 选择的第几项(下标从 0 开始),数字大于 picker-view-column 可选项长度时,选择最后一项。
indicator-style String 设置选择器中间选中框的样式
bindchange EventHandle 当滚动选择,value 改变时触发 change 事件,event.detail = {value: value} value为数组,表示 picker-view 内的 picker-view-column 当前选择的是第几项(下标从 0 开始)

需要注意的是:其中只可放置<picker-view-column/>组件,其他节点不会显示,其孩子节点的高度会自动设置成与picker-view的选中框的高度一致。

有了这个组件,我们是不是能想到:在一个弹出view中设置三个picker-view组件,每个组件中放一个picker-view-column组件用于展示当前列?

value中也可以只放一个number(通常可以放数组元素下标),picker-view会自动将其转为 [下标值]

就像这样:

<view style="width:100%;position:fixed;bottom:0;left:0;z-index:10000;height:500rpx;background-color:white">
 <!-- 仿原生picker的“确定”和“取消”按钮 -->
 <view style="display:flex;width:100%;height:100%">
 <view
 style="position: absolute;top:0;width:100%;height:100rpx;z-index:1000000;display:flex;justify-content:space-between;align-items:center;">
 <view style="width:calc(100% / 3);text-align:center;color:rgba(0,0,0,.6);font-size:39rpx" bindtap="displayer">取消
 </view>
 <view style="width:calc(100% / 3);text-align:center;color:rgb(63,142,255);font-size:39rpx" bindtap="confirm">确定
 </view>
 </view>
 
 <picker-view indicator-style="height: 200rpx;"
 style="width: 100%;height: 300rpx;text-align: center;margin-top:150rpx" value="{{pIndex}}"
 bindchange="changeProvince">
 <picker-view-column>
 <view wx:for="{{placeArray}}" wx:key="name" style="line-height: 77rpx">{{item.name}}</view>
 </picker-view-column>
 </picker-view>
 <picker-view indicator-style="height: 200rpx;"
 style="width: 100%;height: 300rpx;text-align: center;margin-top:150rpx" value="{{cIndex}}"
 bindchange="changeCity">
 <picker-view-column>
 <view wx:for="{{placeArray[pIndex].city}}" wx:key="name" style="line-height: 77rpx">{{item.name}}</view>
 </picker-view-column>
 </picker-view>
 <picker-view indicator-style="height: 200rpx;"
 style="width: 100%;height: 300rpx;text-align: center;margin-top:150rpx" value="{{aIndex}}"
 bindchange="changeArea">
 <picker-view-column>
 <view wx:for="{{placeArray[pIndex].city[cIndex].area}}" wx:key="*this" style="line-height: 77rpx">{{item}}
 </view>
 </picker-view-column>
 </picker-view>
 
 </view>
</view>

可以看到,每一个picker-view-column中做的唯一一件事就是:遍历固定的某一列(某一个数组)并渲染出来。

微信小程序自定义yPicker组件实现省市区三级联动功能

然后如

// js-data
data:{
	placeArray: placeArray,
 province: "",//placeArray[0].name - 省
 pIndex: 0,
 city: "",//placeArray[0].city[0].name - 市
 cIndex: 0,
 area: "",//placeArray[0].city[0].area[0] - 区
 aIndex: 0,
}

上wxml中为每一列(picker-view)都绑定了一个change函数——滑动时触发:

changeProvince: function(e){
 const val = e.detail.value
 this.setData({
 pIndex: val,
 cIndex: 0,
 aIndex: 0,
 province: placeArray[val].name,
 city: placeArray[val].city[0].name,
 area: placeArray[val].city[0].area[0]
 })
},
changeCity: function(e){
 const val = e.detail.value
 this.setData({
 cIndex: val,
 aIndex: 0,
 city: placeArray[this.data.pIndex].city[val].name,
 area: placeArray[this.data.pIndex].city[val].area[0]
 })
},
changeArea: function(e){
 const val = e.detail.value
 this.setData({
 aIndex: val,
 area: placeArray[this.data.pIndex].city[this.data.cIndex].area[val]
 })
},

他们的作用就是把当前选择列的选中元素(出现在indicator-style视野中的元素)暴露到页面上,并将下标定位到这里 —— 以便在页面无刷新下的下一次点开时从这里开始找!
然后最重要的一点就是:在滑动停止时,将另外两列的数据重新定位到第一个!
——当然,你也可以选择在一个picker-view中放置多个picker-view-column组件,这样的话就和上面多列picker一样,需要多个数组联动来传递数据了!

总结

到此这篇关于微信小程序自定义yPicker组件实现省市区三级联动功能的文章就介绍到这了,更多相关微信小程序自定义yPicker组件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
jQuery)扩展jQuery系列之一 模拟alert,confirm(一)
Dec 04 Javascript
Event altKey,ctrlKey,shiftKey属性解析
Dec 18 Javascript
jQuery的context属性用法实例
Dec 27 Javascript
分享两个手机访问pc网站自动跳转手机端网站代码
Dec 24 Javascript
Angular发布1.5正式版,专注于向Angular 2的过渡
Feb 18 Javascript
AngularJS 入门教程之HTML DOM实例详解
Jul 28 Javascript
Mongoose学习全面理解(推荐)
Jan 21 Javascript
javascript编程开发中取色器及封装$函数用法示例
Aug 09 Javascript
vue.js简单配置axios的方法详解
Dec 13 Javascript
JS实现点击拉拽轮播图pc端移动端适配
Sep 05 Javascript
Vue 中 filter 与 computed 的区别与用法解析
Nov 21 Javascript
JS实现进度条动态加载特效
Mar 25 Javascript
解决ant Design Search无法输入内容的问题
Oct 29 #Javascript
js实现随机圆与矩形功能
Oct 29 #Javascript
在vue中使用jsonp进行跨域请求接口操作
Oct 29 #Javascript
基于react项目打包css引用路径错误解决方案
Oct 28 #Javascript
design vue 表格开启列排序的操作
Oct 28 #Javascript
ant design vue导航菜单与路由配置操作
Oct 28 #Javascript
JS实现多功能计算器
Oct 28 #Javascript
You might like
第十四节 命名空间 [14]
2006/10/09 PHP
解决控件遮挡问题:关于有窗口元素和无窗口元素
2007/01/28 PHP
PHP实现MySQL更新记录的代码
2008/06/07 PHP
php隐藏IP地址后两位显示为星号的方法
2014/11/21 PHP
CI框架AR操作(数组形式)实现插入多条sql数据的方法
2016/05/18 PHP
Laravel 实现在Blade模版中使用全局变量代替路径的例子
2019/10/22 PHP
Js 中debug方式
2010/02/07 Javascript
jquery 锁定弹出层实现代码
2010/02/23 Javascript
JavaScript实现瀑布流布局
2020/06/28 Javascript
JavaScript常用函数工具集:lao-utils
2016/03/01 Javascript
简单谈谈json跨域
2016/03/13 Javascript
jQuery插件HighCharts绘制2D圆环图效果示例【附demo源码下载】
2017/03/09 Javascript
React如何避免重渲染
2018/04/10 Javascript
[02:46]2014DOTA2国际邀请赛 选手为你解读比赛MVP充满梦想
2014/07/09 DOTA
[01:10]为家乡而战!完美世界城市挑战赛全国总决赛花絮
2019/07/25 DOTA
OpenCV实现人脸识别
2017/04/07 Python
Python 模拟登陆的两种实现方法
2017/08/10 Python
pytorch 调整某一维度数据顺序的方法
2018/12/08 Python
Python使用到第三方库PyMuPDF图片与pdf相互转换
2019/05/03 Python
Python3.6实现根据电影名称(支持电视剧名称),获取下载链接的方法
2019/08/26 Python
Python matplotlib绘制图形实例(包括点,曲线,注释和箭头)
2020/04/17 Python
使用css3背景渐变中的透明度来设置不同颜色的背景渐变
2014/03/31 HTML / CSS
深入研究HTML5实现图片压缩上传功能
2016/03/25 HTML / CSS
html5实现图片转圈的动画效果——让页面动起来
2017/10/16 HTML / CSS
洗发水广告词
2014/03/13 职场文书
清扬洗发水广告词
2014/03/14 职场文书
《记金华的双龙洞》教学反思
2014/04/19 职场文书
商品陈列协议书
2014/09/29 职场文书
分居协议书范本(律师见证版)
2014/11/26 职场文书
给女朋友道歉的话大全
2015/01/20 职场文书
党员评议自我评价
2015/03/03 职场文书
整脏治乱工作简报
2015/07/21 职场文书
尊师重教主题班会
2015/08/14 职场文书
2015年美容师个人工作总结
2015/10/14 职场文书
python爬虫--selenium模块
2021/03/31 Python
golang 实用库gotable的具体使用
2021/07/01 Golang