在開發的很多電商類型的項目中,免不了會遇到三級聯動選擇地址信息,如果單純的使用文本框給用戶選擇,用戶體檢可能就會差很多。今天我給大家整理了關於小程序開發利用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中引入哦。