微信小程序---自定义三级联动

在开发的很多电商类型的项目中,免不了会遇到三级联动选择地址信息,如果单纯的使用文本框给用户选择,用户体检可能就会差很多。今天我给大家整理了关于小程序开发利用picker-view组件和animation来实现省市区的三级联动
效果如图:
 
首先我觉的大家需要先去阅读下小程序有关picker-view和animation相关的api,然后再跟着这篇文章来理一下思路,一定会有深刻的理解。
 
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中引入哦。

 

posted @ 2019-05-10 12:43  最初的样子  阅读(6912)  评论(0编辑  收藏  举报