近段时间由于一直沉迷王者农药无法自拔,在这先自我检讨...
首先说下今天要做的需求:如下图,是前段时间给APP中添加的客诉功能。
能看到,里面涉及到了选择器多级联动(这里就两级)。然而,上星期三的时候接手了公司的小程序,说是小程序,其实也就两三个页面,要我把APP上的功能加上去,其中包括这个“我要投诉”的页面,综合了下安卓的选择器效果,下面看小程序上做出后的效果如下图:
先大致说下这个页面的所需文件,
是的,小程序的每个页面都需要.js/.json/.wxml/.wxss文件,就像前端 "三剑客"一样,这里是四剑客,但.json其实也是可有可无的,本质上还是三剑客...关于小程序的话题不多说了,对小程序感兴趣的可以私信我讨论哈。
下面开始装X。
先从布局UI开始,也就是 .wxml 和 .wxss(只给出多级联动的部分)
.wxml
<view class="section" >
<view style=" display : flex;flex-direction : row;">
<text class=" text">选择购买门店:</text><text bindtap="cascadePopup" style= " color: #393939;font-size: 32rpx;margin-top : 2px; margin-left:8px;">{{areaSelectedStr}}></text>
</view>
<text style= " color: #393939;font-size: 32rpx;margin-top : 4px;margin-left:114px;">{{detailAddress}}</text>
</view>
//选择器
<view class="modal">
<view class="modal-mask {{maskVisual}}" bindtap="cascadeDismiss"></view>
<view animation="{{animationData}}" class="modal-content">
<view class="modal-header">
<text class="modal-title">请选择门店</text>
<text class="modal-close" bindtap="cascadeDismiss">X</text>
</view>
<view class="modal-body">
<text class="viewpager-title {{current == 0 ? 'area-selected' : ''}}" bindtap="changeCurrent" data-current="0">{{areaName}}</text>
<text class="viewpager-title {{current == 1 ? 'area-selected' : ''}}" bindtap="changeCurrent" data-current="1">{{shopName}}</text>
<text class="viewpager-title {{current == 2 ? 'area-selected' : ''}}" bindtap="changeCurrent" data-current="2">{{detailAddress}}</text>
<view class="viewpager-divider"></view>
<swiper class="swiper-area" current="{{current}}" bindchange="currentChanged">
<block wx:if="{{area_arr.length > 0}}">
<swiper-item>
<scroll-view scroll-y="true" class="viewpager-listview">
<view wx:for="{{area_arr}}" wx:key="index" data-index="{{index}}" bindtap="areaTapped">
<text wx:if="{{index == areaIndex}}" class="area-selected">{{item}}</text>
<text wx:else>{{item}}</text>
</view>
</scroll-view>
</swiper-item>
</block>
<block wx:if="{{shop_arr.length > 0}}">
<swiper-item>
<scroll-view scroll-y="true" class="viewpager-listview">
<view wx:for="{{shop_arr}}" wx:key="index" data-index="{{index}}" bindtap="shopTapped">
<text wx:if="{{index == shopIndex}}" class="area-selected">{{item}}</text>
<text wx:else>{{item}}</text>
</view>
</scroll-view>
</swiper-item>
</block>
<block wx:if="{{detailAddress_tempArr.length > 0}}">
<swiper-item>
<scroll-view scroll-y="true" class="viewpager-listview">
<view wx:for="{{detailAddress_tempArr}}" wx:key="index" data-index="{{index}}" bindtap="detailAddressTapped">
<text wx:if="{{index == detailIndex}}" class="area-selected">{{item}}</text>
<text wx:else>{{item}}</text>
</view>
</scroll-view>
</swiper-item>
</block>
</swiper>
</view>
</view>
</view>
.wxss
.section{
background:white;
margin:2px;
padding:20rpx;
display : flex;
flex-direction : column;
}
.text{
color: #393939;
font-size: 32rpx;
margin-top : 2px;
}
/*跳出的选择器*/
.modal-content {
position: fixed;
bottom: -285px;
left: 0;
width: 100%;
height: 285px;
/*box-shadow: 10rpx 0 30rpx rgba(0,0,0,.9);*/
margin-top: 5px;
background: #fff;
z-index: 999;
}
/*遮罩层*/
.modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
opacity: .8;
z-index: 99;
}
/*弹窗头部*/
.modal-header {
margin: 2px 0;
font-size: 16px;
color: #666;
display: flex;
flex-direction: row;
justify-content: space-between;
line-height: 30px;
}
/*所在地区字样*/
.modal-title {
text-align: center;
width: 100%;
}
/*关闭按钮*/
.modal-close {
width: 20px;
}
.modal-body {
font-size: 14px;
}
/*每级地区标题*/
.viewpager-title {
padding: 0 10px;
/*color: #f03118;*/
line-height: 30px;
}
/*分隔线*/
.viewpager-divider {
width: 100%;
height: 1px;
background: #ccc;
}
/*左右滑动控件*/
.swiper-area {
height:220px;
}
/*地址列表ListView容器*/
.viewpager-listview {
padding-top: 5px;
height: 100%;
}
/*每行地址item项*/
.viewpager-listview view{
line-height: 30px;
padding: 0 10px;
}
/*高亮当前所选地区*/
.area-selected {
color: red;
}
/*初始隐藏*/
.hidden {
display: none;
}
/*运行时显示*/
.show {
display: block;
}
.js文件
var UserInfo = require("../../../js/bean/UserInfo.js");
var ApiUser = require("../../../js/http/ApiUser.js");
var shopss = [];
var detailAddress_arr = [];
Page({
data: {
//购买门店
current:0, //选择器第几页的标识,对应wxml中的current
shopList:[],
area_arr:[],//第一级的数据数组
area_id:[],
shop_arr:[],//第二级的数据数组
shop_id:[],
detailAddress_tempArr:[],//第三级的数据数组
areaSelectedStr: '请选择门店',//area_arr[index]+shop_arr[index] 用来显示于wxml中
maskVisual: 'hidden',
areaName: '请选择',//显示于选择器上面部分的区域名
detailAddress:'可在小票上查看门店',//用来显示于wxml
source: ''
},
onLoad:function(options){
page = this;
this.loadPreData();//加载选择器中的数据
},
//加载平台、门店、投诉类型
loadPreData:function(){
var that = this;
ApiUser.getpreData(function (resp) {
var userInfo = new UserInfo(resp);
if(userInfo.isOK()){
if (userInfo.isSuccess()){
//平台
//...
//投诉类型
//...
// 购买门店
var area_arr = [],
area_id = [];
userInfo.getData().shopsList.forEach(function(e){
area_arr.push(e.area);
area_id.push(e.areaId);
shopss.push(e.shops);
})
that.setData({
//...
shopList:userInfo.getData().shopsList,
area_arr:area_arr,
area_id:area_id
})
}else {
wx.showModal({
title: '提示',
content: userInfo.getMessage(),
success: function(res) {
if (res.confirm) {
console.log('用户点击确定')
}
}
})
}
}else {
if(userInfo.is401()){
wx.showModal({
title: '提示',
content: '请先登录',
success: function(res) {
if (res.confirm) {
console.log('用户点击确定')
}
}
})
}else if(userInfo.is404()){
wx.showModal({
title: '提示',
content: '页面找不到啦',
success: function(res) {
if (res.confirm) {
console.log('用户点击确定')
}
}
})
}else if(userInfo.is500()){
wx.showModal({
title: '提示',
content: '服务器又开小差啦',
success: function(res) {
if (res.confirm) {
console.log('用户点击确定')
}
}
})
}else{
wx.showModal({
title: '提示',
content: userInfo.getMessage(),
success: function(res) {
if (res.confirm) {
console.log('用户点击确定')
}
}
})
}
}
}
)
},
//...
//点击选择门店弹出选择器
cascadePopup: function() {
var animation = wx.createAnimation({
duration: 500,
timingFunction: 'ease-in-out',
});
this.animation = animation;
animation.translateY(-285).step();
this.setData({
animationData: this.animation.export(),
maskVisual: 'show'
});
},
//关闭选择器
cascadeDismiss: function () {
this.animation.translateY(285).step();
this.setData({
animationData: this.animation.export(),
maskVisual: 'hidden'
});
},
//...
//地址选择
areaTapped: function(e) {
// 标识当前点击第一级中的哪个区域,记录其名称与主键id都依赖它
var index = e.currentTarget.dataset.index;
// current为1,使得页面向左滑动一页至商场列表
// areaIndex是商场数据的标识
if(this.data.area_arr[index] == '未知门店'){
this.setData({
areaName: this.data.area_arr[index],
shopName: '',
shop_arr:[],
detailAddress:'暂无详细地址',
detailAddress_tempArr:[],
areaSelectedStr: this.data.area_arr[index] + ' ',
});
this.cascadeDismiss();
}else{
this.setData({
areaName: this.data.area_arr[index],
shopName: '',
detailAddress:'选择门店后显示详细地址',
areaIndex: index,
shopIndex:-1
});
var that = this;
//todo 商场列表赋值
var shop_arr = [],
shop_id = [];
shopss[index].forEach(function(e){
shop_arr.push(e.shopName);
shop_id.push(e.shopId);
detailAddress_arr.push(e.address);
})
that.setData({
shopName:'请选择',
shop_arr:shop_arr,
shop_id: shop_id,
});
that.setData({
current:1
});
}
},
//点击第二级的商场事件,同理上面点击第一级
shopTapped: function (e) {
var index = e.currentTarget.dataset.index;
this.setData({
shopIndex: index,
shopName: this.data.shop_arr[index]
});
var areaSelectedStr = this.data.areaName +" "+ this.data.shopName ;
this.setData({
areaSelectedStr: areaSelectedStr,
detailAddress:detailAddress_arr[index]
});
var detailAddress_tempArr = [];
detailAddress_tempArr.push(detailAddress_arr[index]);
this.setData({
current:2,
detailAddress_tempArr:detailAddress_tempArr
});
},
//点击第三级的详细地址事件,并关闭选择器
detailAddressTapped : function (e) {
this.cascadeDismiss();
},
currentChanged: function (e) {
// swiper滚动使得current值被动变化,用于高亮标记
var current = e.detail.current;
this.setData({
current: current
});
},
changeCurrent: function (e) {
// 记录点击的标题所在的区级级别
var current = e.currentTarget.dataset.current;
this.setData({
current: current
});
},
onReady:function(){
// 页面渲染完成
},
onShow:function(){
// 页面显示
},
onHide:function(){
// 页面隐藏
},
onUnload:function(){
// 页面关闭
}
})
这方面的文章是第一次写,可能可读性较差0.0 有哪些不懂的可以私信我。
以上。