項目地址:https://github.com/leesonp/littleAPP.git
2018.10.25 更新
很多人反映彈出選擇器控件時,不滑動直接點擊“確定”按鈕沒有值返回顯示。其實默認坐標是[0,0,0]的,只是沒有調(diào)用更新數(shù)據(jù)而已。現(xiàn)已更正。
2017.07.21 17:30 更新
之前版本是從頭寫到尾沒有封裝的,有的同學可能看的一臉懵逼,昨天我用微信官方提供的WXML模板(template)對代碼進行了封裝,在模板中定義代碼片段,通過封裝以后我們就可以在不同的地方調(diào)用了。
Demo已上傳到github。
文件組成:
1.模板類(model)
2.舊版未封裝類 (index)
3.新版調(diào)用類 (modelTest)
4.數(shù)據(jù)源 (area.js)
怎么使用呢?
只需在要用到的類中導入模板模板,引入對應后綴的文件,做一些簡單必要操作即可。
以上傳的Demo為例:
// modelTest.js
var model = require('../../model/model.js')
var show = false;
var item = {};
Page({
data: {
item: {
show: show
}
},
//生命周期函數(shù)--監(jiān)聽頁面初次渲染完成
onReady: function (e) {
var that = this;
//請求數(shù)據(jù)
model.updateAreaData(that, 0, e);
},
//點擊選擇城市按鈕顯示picker-view
translate: function (e) {
model.animationEvents(this, 0, true,400);
},
//隱藏picker-view
hiddenFloatView: function (e) {
model.animationEvents(this, 200, false,400);
},
//滑動事件
bindChange: function (e) {
model.updateAreaData(this, 1, e);
item = this.data.item;
this.setData({
province: item.provinces[item.value[0]].name,
city: item.citys[item.value[1]].name,
county: item.countys[item.value[2]].name
});
},
onReachBottom: function (){
},
nono: function (){}
})
<!--modelTest.wxml-->
<import src="../../model/model.wxml"/>
<view class="infoText">{{province}} {{city}} {{county}}</view>
<button class="animation-button" bindtap="translate">選擇城市</button>
<template is="areaData" data="{{...item}}"/>
/* modelTest.wxss */
@import '../../model/model.wxss'
在model.js文件中我就暴露了兩個接口,引入模板后,全部代碼就這些。是不是感覺舒服很多?
代碼簡潔、邏輯清晰,是封裝給我們帶來的好處,希望沒試過封裝的同學可以嘗試下。
-- END --
------------------------------ 分割線 ------------------------------
2017.07.17 更新
本人之前一直從事iOS開發(fā),最近無項目閑來無事研究了下微信小程序。
我沒有像從新學一門語言一樣從頭到尾看一遍文檔,我個人感覺小程序類似前端開發(fā),正好之前對前端也略有涉獵,所以直接就拿我之前iOS的項目的某個模塊練手,不懂的再去查閱官方文檔。
因為有個創(chuàng)建紅包的界面,UITableView的某個cell點擊會彈出選擇區(qū)域和時間選擇器,下面就給大家講一下小程序版是怎樣的一種操作。
在iOS中我用的是UIPickView,體驗還OK。那在小程序中選什么控件呢?查閱官方文檔,有兩種滑動選擇器。
picker:從底部彈起的滾動選擇器,現(xiàn)支持三種選擇器,通過mode來區(qū)分,分別是普通選擇器,時間選擇器,日期選擇器,默認是普通選擇器。因為是固定的,直接pass掉了。但是最開始我以為只有這一種,然后想去百度找找有沒有自定義的。結(jié)果發(fā)現(xiàn)幾乎網(wǎng)上沒有很好的區(qū)域選擇器的方案。我就再回過頭來查閱官方文檔發(fā)現(xiàn)還有個picker-view。
picker-view:嵌入頁面的滾動選擇器。官方的示例咋一看還是時間選擇器,以為也是定死的呢。但是看代碼就可以發(fā)現(xiàn),其實跟iOS的寫法邏輯相似。
既然相似我們就可以著手寫代碼了。但是開始寫之前首先我們要拿到省市區(qū)縣的數(shù)據(jù)。網(wǎng)上搜索下中國行政區(qū)域可以找到很多,我選了這個。下載下來是txt文件的Json數(shù)據(jù)。那怎么導入工程呢? 有兩種方法:
1.在utils文件夾下新建一個js文件,寫一個函數(shù)把txt里的json數(shù)據(jù)復制粘貼進去,然后在需要的類目下調(diào)用這個函數(shù)接收返回值就行了。
//area.js
function getAreaInfo(callBack){
var str =["此處粘貼json數(shù)據(jù)":... ];//因數(shù)據(jù)量太大就不在此處全部展示,知道是個數(shù)組就行了。
callBack(str);
}
module.exports.getAreaInfo = getAreaInfo;
------------------------------ 分割線 ------------------------------
//index.js
var area = require('../../utils/area.js')
...
Page({
data: { },
onLoad: function (options) {
var that = this;
//獲取省市區(qū)縣數(shù)據(jù)
area.getAreaInfo(function (arr) {
});
}
})
...
2.寫一個接口調(diào)用,我自己就是寫的一個PHP接口。
//php代碼
$filename = "ChinaArea.txt";//網(wǎng)絡(luò)上下載的文件(PHP或Java需要配置環(huán)境才能請求到數(shù)據(jù))。
$json_string = file_get_contents($filename);
echo print_r($json_string,true);
個人建議還是不要把數(shù)據(jù)源直接寫在項目,因為小程序包是有大小限制的如若超過是無法提交的所以建議寫接口,或者拿別人現(xiàn)成的接口。
話不多說直接貼代碼吧。(代碼已做必要注釋)
<!--index.wxml-->
<view class="infoText">{{province}} {{city}} {{county}}</view>
<view class="aaaa" >
<button class="animation-button" bindtap="translate">選擇城市</button>
</view>
<view class="animation-element-wrapper" animation="{{animation}}" style="visibility:{{show ? 'visible':'hidden'}}" bindtap="hiddenFloatView" data-id="444">
<view class="animation-element" catchtap="nono">
<text class="left-bt" catchtap="hiddenFloatView" data-id="555">取消</text>
<text class="right-bt" catchtap="hiddenFloatView" data-id="666">確定</text>
<view class="line"></view>
<picker-view indicator-style = "height: 50rpx;" value="{{value}}" bindchange="bindChange" catchtap="nono">
<!--省-->
<picker-view-column>
<view wx:for="{{provinces}}" wx:key="" >
{{item.name}}
</view>
</picker-view-column>
<!--地級市-->
<picker-view-column>
<view wx:for="{{citys}}" wx:key="" >
{{item.name}}
</view>
</picker-view-column>
<!--區(qū)縣-->
<picker-view-column>
<view wx:for="{{countys}}" wx:key="" >
{{item.name}}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
/**index.wxss**/
page{
background-color: rgba(255, 255, 255, 1);
}
.infoText{
margin-top: 20rpx;
text-align: center;
width: 100%;
justify-content: center;
}
picker-view{
background-color: white;
padding: 0;
width: 100%;
height: 380rpx;
bottom: 0;
position: fixed;
}
picker-view-column view{
vertical-align:middle;
font-size: 28rpx;
line-height: 28rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
/* ----------------------------------------- */
.animation-element-wrapper {
display: flex;
position: fixed;
left: 0;
top:0;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.6);
}
.animation-element {
display: flex;
position: fixed;
width: 100%;
height: 470rpx;
bottom: 0;
background-color: rgba(255, 255, 255, 1);
}
.animation-button {
top:20rpx;
width: 290rpx;
height: 100rpx;
align-items:center;
}
text{
color: #999999;
display: inline-flex;
position: fixed;
margin-top: 20rpx;
height: 50rpx;
text-align: center;
line-height: 50rpx;
font-size: 34rpx;
font-family: Arial, Helvetica, sans-serif;
}
.left-bt{
left: 30rpx;
}
.right-bt {
right: 30rpx;
}
.line{
display: block;
position: fixed;
height: 1rpx;
width: 100%;
margin-top: 89rpx;
background-color: #eeeeee;
}
//index.js
//獲取應用實例
var area = require('../../utils/area.js')
var areaInfo = [];//所有省市區(qū)縣數(shù)據(jù)
var provinces = [];//省
var citys = [];//城市
var countys = [];//區(qū)縣
var index = [0, 0, 0];
var cellId;
var t = 0;
var show = false;
var moveY = 200;
Page({
data: {
show: show,
provinces: provinces,
citys: citys,
countys: countys,
value: [0, 0, 0]
},
//滑動事件
bindChange: function (e) {
var val = e.detail.value
//判斷滑動的是第幾個column
//若省份column做了滑動則定位到地級市和區(qū)縣第一位
if (index[0] != val[0]) {
val[1] = 0;
val[2] = 0;
getCityArr(val[0], this);//獲取地級市數(shù)據(jù)
getCountyInfo(val[0], val[1], this);//獲取區(qū)縣數(shù)據(jù)
} else { //若省份column未做滑動,地級市做了滑動則定位區(qū)縣第一位
if (index[1] != val[1]) {
val[2] = 0;
getCountyInfo(val[0], val[1], this);//獲取區(qū)縣數(shù)據(jù)
}
}
index = val;
console.log(index + " => " + val);
//更新數(shù)據(jù)
this.setData({
value: [val[0], val[1], val[2]],
province: provinces[val[0]].name,
city: citys[val[1]].name,
county: countys[val[2]].name
})
},
onLoad: function (options) {
cellId = options.cellId;
var that = this;
var date = new Date()
console.log(date.getFullYear() + "年" + (date.getMonth() + 1) + "月" + date.getDate() + "日");
//獲取省市區(qū)縣數(shù)據(jù)
area.getAreaInfo(function (arr) {
areaInfo = arr;
//獲取省份數(shù)據(jù)
getProvinceData(that);
});
},
// ------------------- 分割線 --------------------
onReady: function () {
this.animation = wx.createAnimation({
transformOrigin: "50% 50%",
duration: 0,
timingFunction: "ease",
delay: 0
}
)
this.animation.translateY(200 + 'vh').step();
this.setData({
animation: this.animation.export(),
show: show
})
},
//移動按鈕點擊事件
translate: function (e) {
if (t == 0) {
moveY = 0;
show = false;
t = 1;
} else {
moveY = 200;
show = true;
t = 0;
}
// this.animation.translate(arr[0], arr[1]).step();
animationEvents(this,moveY, show);
},
//隱藏彈窗浮層
hiddenFloatView(e){
console.log(e);
moveY = 200;
show = true;
t = 0;
animationEvents(this,moveY, show);
},
//頁面滑至底部事件
onReachBottom: function () {
// Do something when page reach bottom.
}
})
//動畫事件
function animationEvents(that,moveY,show){
console.log("moveY:" + moveY + "\nshow:" + show);
that.animation = wx.createAnimation({
transformOrigin: "50% 50%",
duration: 400,
timingFunction: "ease",
delay: 0
}
)
that.animation.translateY(moveY + 'vh').step()
that.setData({
animation: that.animation.export(),
show: show
})
}
// ---------------- 分割線 ----------------
//獲取省份數(shù)據(jù)
function getProvinceData(that) {
var s;
provinces = [];
var num = 0;
for (var i = 0; i < areaInfo.length; i++) {
s = areaInfo[i];
if (s.di == "00" && s.xian == "00") {
provinces[num] = s;
num++;
}
}
that.setData({
provinces: provinces
})
//初始化調(diào)一次
getCityArr(0, that);
getCountyInfo(0, 0, that);
that.setData({
province: "北京市",
city: "市轄區(qū)",
county: "東城區(qū)",
})
}
// 獲取地級市數(shù)據(jù)
function getCityArr(count, that) {
var c;
citys = [];
var num = 0;
for (var i = 0; i < areaInfo.length; i++) {
c = areaInfo[i];
if (c.xian == "00" && c.sheng == provinces[count].sheng && c.di != "00") {
citys[num] = c;
num++;
}
}
if (citys.length == 0) {
citys[0] = { name: '' };
}
that.setData({
city: "",
citys: citys,
value: [count, 0, 0]
})
}
// 獲取區(qū)縣數(shù)據(jù)
function getCountyInfo(column0, column1, that) {
var c;
countys = [];
var num = 0;
for (var i = 0; i < areaInfo.length; i++) {
c = areaInfo[i];
if (c.xian != "00" && c.sheng == provinces[column0].sheng && c.di == citys[column1].di) {
countys[num] = c;
num++;
}
}
if(countys.length == 0){
countys[0] = {name:''};
}
that.setData({
county: "",
countys: countys,
value: [column0, column1, 0]
})
}
最終效果:
本文的難點主要集中在滑動的是哪一列、數(shù)據(jù)的處理、每次滑動每一列數(shù)據(jù)的更新數(shù)組的定位:
1.滑動第一列: 第二列和第三列位置都置零;更新數(shù)組citys和countys。
2.滑動第二列: 第一列不動,第三列置零;更新數(shù)組countys。
3.滑動第三列: 第一列和第二列都不動;數(shù)據(jù)不用更新,改變val[2]即可。
。
處理不好的話體驗會很不好,會有閃跳的感覺。
項目地址:https://github.com/leesonp/littleAPP.git
這是我第一次寫文章,寫的不好或者有紕漏的地方,希望大家多多包容、指正,謝謝。