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

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



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

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

笔者仔细翻阅了官方文档和许多博主文章发现提出了各种各样的解决方案(但很遗憾没发现有博主详细公开代码),但是对于这样一个其实并不需要“联动”、列数也不固定的功能,用多列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

正式开始

不知大家有没有使用过,或听过小程序的 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中做的唯一一件事就是:遍历固定的某一列(某一个数组)并渲染出来。

然后如

// 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组件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 微信小程序 ecshop地址三级联动实现实例代码

    微信小程序 ecshop地址3级联动实现实例代码 picker标签,官方给出的实例: <view class="section"> <view class="section__title">地区选择器</view> <picker bindchange="bindPickerChange" value="{{index}}" range="{{array}}">

  • 微信小程序 使用picker封装省市区三级联动实例代码

    微信小程序 使用picker封装省市区三级联动实例 目前学习小程序更多的是看看能否二次封装其它组件,利于以后能快速开发各种小程序应用.目前发现picker的selector模式只有一级下拉,那么我们是否可以通过3个picker来实现三级联动模板的形式来引入其它页面中呢?答案是肯定可以的.那么我的思路是这样的: 1.使用template模板语法进行封装,数据从页面传入 2.根据picker组件的语法,range只能是一组中文地区数组,但是我们需要每个地区的唯一码来触发下一级联动数据.这样,我的做法

  • 微信小程序三级联动地址选择器的实例代码

    本文介绍了微信小程序三级联动地址选择器的实例代码,分享给大家,有需要的可以一起了解一下 在一些电商类的小程序中,地址选择这个功能一般是必备的,一般的收货信息都需要有一个能选择省市县的控件,当然也有些人为了省事就直接写了一个供输入的input,那么这样做的缺点不言而喻,而且用户体验也不是那么的好,今天的这篇文章就分享一下微信小程序地址选择的实现.省市县的数据以及区域码可以从国家统计局查询到,具体可以自己搜一下.照例先上源码和效果图 源码传送门 picker和picker-view组件 在正式介绍实

  • 微信小程序三级联动选择器使用方法

    本文实例为大家分享了微信小程序三级联动选择器的具体代码,供大家参考,具体内容如下 效果图 实现原理 利用微信小程序的picker组件,其中: 1,普通选择器:mode = selector实现一级选择实例: 2,省市区选择器:mode = region实现省市区三级联动: 3, 多列选择器:mode = multiSelector实现二级和三级联动的10以内数字的乘法. WXML <view class="tui-picker-content"> <view clas

  • 微信小程序实现选择地址省市区三级联动

    本文实例为大家分享了微信小程序实现选择地址省市区三级联动的具体代码,供大家参考,具体内容如下 微信原生地址API,缺少省市区code,因此自己写了一个收货地址 思路:在onload预先加载全部省和第一个省的全部市和区,加载全部会导致几秒的事件阻塞.点击选择地址弹窗后,按需加载操作,滑动省加载对应的市和第一个市对应的区,滑动市加载区,滑动区只更改区的值 onLoad: function(options) { var that = this; // 此文件为全部省以及第一个省的市和区 var cit

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

    自从上一篇文章:微信小程序自定义日历组件及flex布局最后一行对齐问题分析 出来以后,有人私聊我说能不能从头分析一下我开源的自定义组件?一直没时间.这不,最近项目中有个需求是 省市区三级联动 ,我就顺便从组件库中的第一个 「扩展日期-时间picker(点此直接至GitHub,欢迎star)」组件开始说一下这两个功能的实现. 简单说一下"自定义日期-时间组件" 它的背景是项目的第一版当时发现微信小程序内置的日期组件:picker只能精确到某一天(年月日),但是我们很多时候需要年月日时分甚

  • 微信小程序自定义地址组件

    本文实例为大家分享了微信小程序自定义地址组件的具体代码,供大家参考,具体内容如下 项目需求 需要调用后台传过来的地址,存储地址时存的是地址的id,所以市面上的地址组件均不符合我的需求,只能自定义一个. 技术选取 picker-view和picker-view-column 核心代码 region.wxml <!--地址选择器--> <view wx:if="{{show}}" class="region-picker" catchtap="

  • 微信小程序自定义tabBar组件开发详解

    本文实例为大家分享了微信小程序自定义tabBar组件的具体代码,供大家参考,具体内容如下 以下代码保存在github地址 先看一看目录 template文件夹里存放tabbar模板. template/template.wxml <template name="tabBar"> <view class="tabBar"> <block wx:for="{{tabBar}}" wx:for-item="ite

  • 微信小程序自定义toast组件的方法详解【含动画】

    本文实例讲述了微信小程序自定义toast组件的方法.分享给大家供大家参考,具体如下: 怎么创建就不说了,前面一篇有 微信小程序自定义prompt组件 直接上代码 wxml <!-- components/toast/toast.wxml --> <view class="toast-box {{isShow? 'show':''}}" animation="{{animationData}}"> <view class="to

  • 微信小程序自定义prompt组件步骤详解

    步骤一:新建一个component的文件夹,用来放所有的自定义组件:  步骤二:在该目录下新建一个prompt的文件夹,用来放prompt组件:  步骤三:右击–>新建–>component 直接上代码 wxml <view class="prompt-box" hidden="{{isHidden}}"> <view class="prompt-content contentFontColor"> <v

  • 微信小程序自定义顶部组件customHeader的示例代码

    1.开启配置自定义顶部 { "window": { "navigationStyle":"custom" } } 在app.json的文件window配置"navigationStyle": "custom"属性即可 2.自定义顶部计算原理 2.1 获取系统状态栏的高度和屏幕宽度 使用wx.getSystemInfo这个函数获取系统状态栏的高度和屏幕宽度. 2.2 获取右上角胶囊位置信息 使用wx.getM

  • 浅析微信小程序自定义日历组件及flex布局最后一行对齐问题

    最近为我开源的小项目:微信小程序扩展自定义组件库(点击去GitHub) 增加了一个新组件 -- 日历组件. 效果演示: 在编写过程中,因为大家都知道,日历组件是有固定行数和每一行的固定列数的(即使当前方块内没有值),所以结合小程序"数据优先"的特点,最合适的布局方式一定是flex了! 先说一下大致思路(布局上),笔者将整个组件分为两部分:分别是 头部的当前日期(年月)显示,以及左右两侧的切换按钮 当前切换月份的日期显示 头部的布局自不多说:一个 display:flex; 加上 ali

  • 微信小程序自定义tabbar组件

    本文实例为大家分享了微信小程序自定义tabbar组件的具体代码,供大家参考,具体内容如下 由于项目需求,必须自己写组件: 第一步:在App.json中配置tabBar,自定也组件也必须配置,"custom": true,list里配置所有的tabbar页面. "tabBar": { "custom": true, "color": "red", "selectedColor": &quo

  • 微信小程序自定义波浪组件使用方法详解

    最近看到好多app上有波浪背景,有动态的,有静态的,这里是在小程序中用得动态. 先看看效果图:里面的文本是组件内部定义的. 这是用两个svg的图片用css关键帧动画做的效果(这里谢谢子弹短信里前端群的小伙伴提供的web版的css动画文件) 在小程序中使用,注意一个问题:就是svg不可以直接使用,需要转为base64(这个大家应该有收藏吧),这里我已经转换好了,在下面的wxss中. 这里顺便用一下自定义组件: 首先定义组件 wave wave.wxml:这里我默认是用得显示个人信息.其中isSho

  • 微信小程序非swiper组件实现的自定义伪3D轮播图效果示例

    本文实例讲述了微信小程序非swiper组件实现的自定义伪3D轮播图效果.分享给大家供大家参考,具体如下: 效果如下: 我用了很笨的方法实现的,大致就是: 1.当前点击的div(view)如果前后都有内容,那么,当前div(view)就设置到中间,前一个就设置到左边,前一个的前面所有全部设置到最左边,后面一个设置到右边,后面所有设置到最右边 2.当前点击的div(view)如果前面无内容,即第一个,那么,当前div(view)设置到中间,后面一个设置到右边,后面所有设置到最右边 3.当前点击的di

随机推荐