微信小程序的yPicker组件如何实现省市区三级联动,形成长尾词?

2026-04-02 09:511阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2408个文字,预计阅读时间需要10分钟。

微信小程序的yPicker组件如何实现省市区三级联动,形成长尾词?

从上一篇文章中,我们探讨了微信小程序自定义日历组件及flex布局的最后一行对齐问题。接下来,有人私下询问我,能否从源头分析一下我开源的自定义组件?其实,一提到开源,很多人会想当然地认为需要花费大量时间。但实际上,并非如此。

最近的项目中,我确实使用了一个自定义组件。这个组件的设计初衷是为了解决特定场景下的需求,比如日期选择、事件提醒等。下面,我将简要分析一下这个组件的设计思路。

首先,组件的核心功能是展示日期,并提供基本的交互操作,如选择、切换月份等。为了实现这个功能,我采用了以下设计:

1. 日期展示:使用flex布局,将日期以网格形式展示,方便用户直观地查看和选择。

2.交互操作:通过绑定事件,实现点击日期、切换月份等操作。

3.自定义配置:允许用户根据需求自定义组件的样式、功能等。

在设计过程中,我主要考虑了以下几点:

- 易用性:组件应易于使用,用户能够快速上手。

- 灵活性:组件应支持多种配置,满足不同场景的需求。- 性能:组件应具有良好的性能,确保在复杂场景下也能流畅运行。

开源这个组件,主要是希望它能帮助到更多有类似需求的人。当然,开源也意味着需要投入一定的时间和精力进行维护和更新。但在我看来,这种投入是值得的,因为它不仅能让我得到反馈和改进的机会,还能让我结识更多志同道合的朋友。

总之,开源的自定义组件并非遥不可及,关键在于找到合适的切入点,并付出相应的努力。希望我的分享能对大家有所启发。

自从上一篇文章:微信小程序自定义日历组件及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中元素时的第二个索引!


说说省市区三级联动实现

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

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

提取码: wc3g

微信小程序的yPicker组件如何实现省市区三级联动,形成长尾词?

使用时按如下引入即可:(是一个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组件内容请搜索易盾网络以前的文章或继续浏览下面的相关文章希望大家以后多多支持易盾网络!

本文共计2408个文字,预计阅读时间需要10分钟。

微信小程序的yPicker组件如何实现省市区三级联动,形成长尾词?

从上一篇文章中,我们探讨了微信小程序自定义日历组件及flex布局的最后一行对齐问题。接下来,有人私下询问我,能否从源头分析一下我开源的自定义组件?其实,一提到开源,很多人会想当然地认为需要花费大量时间。但实际上,并非如此。

最近的项目中,我确实使用了一个自定义组件。这个组件的设计初衷是为了解决特定场景下的需求,比如日期选择、事件提醒等。下面,我将简要分析一下这个组件的设计思路。

首先,组件的核心功能是展示日期,并提供基本的交互操作,如选择、切换月份等。为了实现这个功能,我采用了以下设计:

1. 日期展示:使用flex布局,将日期以网格形式展示,方便用户直观地查看和选择。

2.交互操作:通过绑定事件,实现点击日期、切换月份等操作。

3.自定义配置:允许用户根据需求自定义组件的样式、功能等。

在设计过程中,我主要考虑了以下几点:

- 易用性:组件应易于使用,用户能够快速上手。

- 灵活性:组件应支持多种配置,满足不同场景的需求。- 性能:组件应具有良好的性能,确保在复杂场景下也能流畅运行。

开源这个组件,主要是希望它能帮助到更多有类似需求的人。当然,开源也意味着需要投入一定的时间和精力进行维护和更新。但在我看来,这种投入是值得的,因为它不仅能让我得到反馈和改进的机会,还能让我结识更多志同道合的朋友。

总之,开源的自定义组件并非遥不可及,关键在于找到合适的切入点,并付出相应的努力。希望我的分享能对大家有所启发。

自从上一篇文章:微信小程序自定义日历组件及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中元素时的第二个索引!


说说省市区三级联动实现

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

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

提取码: wc3g

微信小程序的yPicker组件如何实现省市区三级联动,形成长尾词?

使用时按如下引入即可:(是一个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组件内容请搜索易盾网络以前的文章或继续浏览下面的相关文章希望大家以后多多支持易盾网络!