在开发的很多电商类型的项目中,免不了会遇到三级联动选择地址信息,如果单纯的使用文本框给用户选择,用户体检可能就会差很多。今天我给大家整理了关于小程序开发利用picker-view组件和animation来实现省市区的三级联动
效果如图:
首先我觉的大家需要先去阅读下小程序有关picker-view和animation相关的api,然后再跟着这篇文章来理一下思路,一定会有深刻的理解。
文档连接传送门:https://developers.weixin.qq.com/miniprogram/dev/component/picker-view.html?search-key=picker-view
DOMO如下:
第一步:先布局wml页面:
1 <view class="picker-view" animation="{{animationAddressMenu}}" style="visibility:{{addressMenuIsShow ? ‘visible‘:‘hidden‘}}">
2 <!-- 确认取消按钮 -->
3 <view class=‘btn‘>
4 <text catchtap="cityCancel">取消</text>
5 <text style="float: right" catchtap="citySure">确定</text>
6 </view>
7 <!-- 选择地址 -->
8 <picker-view class=‘cont‘ bindchange="cityChange" value="{{value}}" wx:key="">
9 <!-- 省 -->
10 <picker-view-column>
11 <view wx:for="{{provinces}}" class="picker-item" wx:key="{{index}}">{{item.name}}</view>
12 </picker-view-column>
13 <!-- 市 -->
14 <picker-view-column>
15 <view wx:for="{{citys}}" class="picker-item" wx:key="index">{{item.name}}</view>
16 </picker-view-column>
17 <!-- 区 -->
18 <picker-view-column>
19 <view wx:for="{{areas}}" class="picker-item" wx:key="index">{{item.name}}</view>
20 </picker-view-column>
21 </picker-view>
22 </view>
23
24 <button bindtap=‘select‘ class=‘select‘>地址选择</button>
25 <view class=‘address‘>{{areaInfo}}</view>
picker-view作为外层标签包裹picker-view-column,有几个picker-view-column就有几列数据。
第二步:设置其样式:
1 .picker-view { 2 width: 100%; 3 display: flex; 4 z-index:12; 5 background-color: #fff; 6 background: rgba(0, 0, 0, .2); 7 flex-direction: column; 8 justify-content: center; 9 align-items: center; 10 position: fixed; 11 bottom: 0; 12 left: 0rpx; 13 height: 40vh; 14 } 15 .btn { 16 width: 100%; 17 height: 90rpx; 18 padding: 0 24rpx; 19 box-sizing: border-box; 20 line-height: 90rpx; 21 text-align: center; 22 display: flex; 23 background: rgba(255,255,255,.8); 24 justify-content: space-between; 25 } 26 .cont { 27 width: 100%; 28 height: 389rpx; 29 } 30 .picker-item { 31 line-height: 70rpx; 32 margin-left: 5rpx; 33 margin-right: 5rpx; 34 text-align: center; 35 } 36 .address { 37 width: 100%; 38 height: 90rpx; 39 line-height: 90rpx; 40 text-align: center; 41 border-bottom: 1rpx solid #f1f1f1; 42 }
wxss中值得注意的是vh单位:
vh:viewpoint height,视窗高度,1vh等于视窗高度的1%。
第三步:实现省市区选择的业务逻辑和动画画出的实现:
1 var address = require("../mock.js")
2 Page({
3 /**
4 * 控件当前显示的数据
5 * provinces:所有省份
6 * citys 选择省对应的所有市,
7 * areas 选择市对应的所有区
8 * areaInfo:点击确定时选择的省市县结果
9 * animationAddressMenu:动画
10 * addressMenuIsShow:是否可见
11 */
12 data: {
13 animationAddressMenu: {},
14 addressMenuIsShow: false,
15 value: [0, 0, 0],
16 provinces: [],
17 citys: [],
18 areas: [],
19 areaInfo: ‘‘
20 },
21
22 /**
23 * 生命周期函数--监听页面加载
24 */
25 onLoad: function (options) {
26 // 默认联动显示北京
27 var id = address.provinces[0].id
28 this.setData({
29 provinces: address.provinces,
30 citys: address.citys[id],
31 areas: address.areas[address.citys[id][0].id],
32 })
33 },
34 // 点击所在地区弹出选择框
35 select: function (e) {
36 // 如果已经显示,不在执行显示动画
37 if (this.data.addressMenuIsShow) {
38 return false
39 } else {
40 // 执行显示动画
41 this.startAddressAnimation(true)
42 }
43 },
44 // 执行动画
45 startAddressAnimation: function (isShow) {
46 if (isShow) {
47 // vh是用来表示尺寸的单位,高度全屏是100vh
48 this.animation.translateY(0 + ‘vh‘).step()
49 } else {
50 this.animation.translateY(40 + ‘vh‘).step()
51 }
52 this.setData({
53 animationAddressMenu: this.animation.export(),
54 addressMenuIsShow: isShow,
55 })
56 },
57 // 点击地区选择取消按钮
58 cityCancel: function (e) {
59 this.startAddressAnimation(false)
60 },
61 // 点击地区选择确定按钮
62 citySure: function (e) {
63 var that = this
64 var city = that.data.city
65 var value = that.data.value
66 this.startAddressAnimation(false)
67 // 将选择的城市信息显示到输入框
68 var areaInfo = that.data.provinces[value[0]].name + ‘·‘ + that.data.citys[value[1]].name + ‘·‘ + that.data.areas[value[2]].name
69 that.setData({
70 areaInfo: areaInfo,
71 })
72 },
73 // 处理省市县联动逻辑
74 cityChange: function (e) {
75 var value = e.detail.value
76 var provinces = this.data.provinces
77 var citys = this.data.citys
78 var areas = this.data.areas
79 var provinceNum = value[0]
80 var cityNum = value[1]
81 var countyNum = value[2]
82 // 如果省份选择项和之前不一样,表示滑动了省份,此时市默认是省的第一组数据,
83 if (this.data.value[0] != provinceNum) {
84 var id = provinces[provinceNum].id
85 this.setData({
86 value: [provinceNum, 0, 0],
87 citys: address.citys[id],
88 areas: address.areas[address.citys[id][0].id],
89 })
90 } else if (this.data.value[1] != cityNum) {
91 // 滑动选择了第二项数据,即市,此时区显示省市对应的第一组数据
92 var id = citys[cityNum].id
93 this.setData({
94 value: [provinceNum, cityNum, 0],
95 areas: address.areas[citys[cityNum].id],
96 })
97 } else {
98 // 滑动选择了区
99 this.setData({
100 value: [provinceNum, cityNum, countyNum]
101 })
102 }
103 },
104 onShow: function () {
105 var animation = wx.createAnimation({
106 duration: 500,
107 timingFunction: ‘linear‘,
108 })
109 this.animation = animation
110 }
111 })
难点:
主要是再实现省市区联动的时候,需要根据省份的id去查找对应的市,然后根据选择的市查找对应的区。这里比较复杂,提供方法:多打断点,明确输出结果是什么。
动画的实现:通过实例化对象,再onShow中将animation放到全局中,然后创建方法,将方法通过 this.animation.translateY(0 + ‘vh‘).step()导出,然后通过将 this.setData({animationAddressMenu: this.animation.export()})导出就可以了,不过,别忘了在wxml中引入哦。