想实现一个可以选择年份和时间段的日期选择器,如下所示 微信小程序自带的picker组件虽然能实现如上的内容,但不能实现样式的修改,不太符合小程序的设计主题,所以考虑了以下两种方法来实现如上的设计。
1.自定义date-picker
把要实现的date-picker封装为一个组件,组建内套用小程序自带的picker-view组件,其中picker_view-column表示不同的选择列,这样可以方便地实现样式的自定义。
实现效果:
具体实现
wxml文件:
<view class="mask" wx:if="{{isShow}}" catchtap="cancel">
<view class="content" style="height:800rpx" animation="{{animation}}">
<view class="top">
<view class="top-text top-left-color" hover-class="top-left-color-hover" catchtap="cancel">取消</view>
<view class="top-text top-right-color" hover-class="top-right-color-hover" catchtap="confirm">确定</view>
</view>
<picker-view style="width: 100%; height: 80%;" value="{{value}}" bindchange="change" catchtap="no">
<picker-view-column>
<view wx:for="{{date_list}}" wx:key="date_list" class="item">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view wx:for="{{time_list}}" wx:key="time_list" class="item">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</view>
wxss文件:
.mask {
position: fixed;
width: 100%;
height: 100%;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
background-color: rgba(0, 0, 0, 0.7);
z-index: 9999;
flex-direction: column;
justify-content: flex-end;
}
.content {
display: flex;
flex-direction: column;
width: 100%;
background: white;
border-top-right-radius: 20rpx;
border-top-left-radius: 20rpx;
}
.top {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 100rpx;
border-bottom: 1rpx solid #d3cfcf;
}
.top-text {
font-size: 30rpx;
width: 150rpx;
height: 100rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.top-left-color {
color: #878787;
}
.top-left-color-hover {
color: #f1eaea;
}
.top-right-color {
color: #1296DB;
}
.top-right-color-hover {
color: #82ccf3;
}
.item {
width: 100%;
align-items: center;
justify-content: center;
display: flex;
flex-direction: row;
font-size: 18px;
}
Component({
properties: {
range: {
type: Number,
value: 10
},
start_time: {
type: Number,
value: 8
},
step: {
type: Number
},
end_time: {
type: Number,
value: 22
}
},
data: {
isShow: false,
selectDate: "",
dialogh: 0,
date_list: [],
time_list: []
},
attached: function () {
let start_day = this.ts_string(new Date().getTime());
console.log(start_day);
console.log(new Date());
let end_day = this.ts_string(new Date().setDate(new Date().getDate() + this.properties.range))
let date_list = this.getDiffDate(start_day, end_day);
let time_list = this.getTimeList(this.properties.start_time, this.properties.end_time, this.properties.step);
console.log(time_list);
this.setData({
date_list: date_list,
time_list: time_list,
})
this.animation = wx.createAnimation({
duration: 300
})
let dialoghpx = 800 / 750 * wx.getSystemInfoSync().windowWidth
this.setData({
dialogh: dialoghpx,
selectDate: this.data.date_list[0] + this.data.time_list[0]
})
},
methods: {
getDiffDate(start, end) {
let startTime = new Date(start);
let endTime = new Date(end);
let dateArr = [];
while ((endTime.getTime() - startTime.getTime()) >= 0) {
dateArr.push(this.ts_string(startTime.getTime()));
startTime.setDate(startTime.getDate() + 1);
}
return dateArr;
},
zfill(num, length) {
return (Array(length).join('0') + num).slice(-length);
},
ts_string(timestamp) {
let d = new Date(timestamp);
let day = "";
switch (d.getDay()) {
case 1:
day = "周一";
break;
case 2:
day = "周二";
break;
case 3:
day = "周三";
break;
case 4:
day = "周四";
break;
case 5:
day = "周五";
break;
case 6:
day = "周六";
break;
case 0:
day = "周日";
break;
}
let string = (d.getFullYear()) + "-" +
this.zfill((d.getMonth() + 1), 2) + "-" +
this.zfill((d.getDate()), 2) + " (" + day + ")"
return string
},
getTimeList(start, end, step) {
let start_time = new Date();
start_time.setHours(start, 0, 0);
console.log(start_time);
let end_time = new Date();
end_time.setHours(end, 0, 0);
let startG = start_time.getTime();
let endG = end_time.getTime();
let step_ms = step * 60 * 1000;
let timeArr = [];
while (startG < endG) {
let time = this.timeAdd(startG, step_ms);
timeArr.push(time);
startG += step_ms;
}
return timeArr;
},
timeAdd(time1, add) {
var nd = new Date(time1);
var hh1 = nd.getHours();
var mm1 = nd.getMinutes();
if (hh1 <= 9) hh1 = "0" + hh1;
if (mm1 <= 9) mm1 = "0" + mm1;
nd = nd.valueOf();
nd = nd + Number(add);
nd = new Date(nd);
var hh2 = nd.getHours();
var mm2 = nd.getMinutes();
if (hh2 <= 9) hh2 = "0" + hh2;
if (mm2 <= 9) mm2 = "0" + mm2;
var time = hh1 + ":" + mm1 + "-" + hh2 + ":" + mm2;
return time;
},
change: function (e) {
const val = e.detail.value;
let select = this.data.date_list[val[0]] + this.data.time_list[val[1]]
console.log(select);
this.setData({
selectDate: select
})
},
showDialog() {
this.setData({
isShow: true
})
this.animation.translateY(this.data.dialogh).translateY(0).step()
this.setData({
animation: this.animation.export()
})
},
dimsss() {
this.animation.translateY(this.data.dialogh).step()
this.setData({
animation: this.animation.export()
})
setTimeout(() => {
this.setData({
isShow: false
})
}, 300)
},
cancel() {
this.triggerEvent("cancel")
this.dimsss()
},
confirm() {
this.triggerEvent("confirm", {
selectDate: this.data.selectDate
})
this.dimsss()
}
}
})
组件的使用
想在父组件中使用封装好的date-picker组件,先要在父组件的json文件中声明。
{
"usingComponents": {
"date-picker": "../../components/date-picker/date-picker"
},
}
如果想实现简单的选择时间段并在页面中显示的功能,父组件代码如下编写即可。 父组件wxml文件:
<view class="option" bindtap="timeOpen" style="font-size: 16px;">
{{selectDate}}
</view>
<date-picker id="picker" range="8" step="40" bindconfirm="confirm"></date-picker>
父组件js文件:
Page({
data: {
selectDate: "",
machineShow: false,
},
onLoad: function () {
this.picker = this.selectComponent("#picker")
},
timeOpen() {
this.picker.showDialog();
},
confirm(e) {
this.setData({
selectDate: e.detail.selectDate
})
},
})
2.结合vant weapp的date-picker
自定义的date-picker组件已经可以实现想实现的功能,但自定义的组件样式不够美观。这时,我注意到了小程序可以使用vant的组件库,组件库多列选择器的样式可以自由修改,而且自带样式已经足够美观,所以下面考虑结合vant组件库实现date-picker。
实现效果
具体实现
使用vant weapp的picker组件和popup组件可以更简洁地实现想要的效果,打造自定义的date-picker组件。
首先需要在编写组件的json文件中导入vant weapp的相应组件
{
"component": true,
"usingComponents": {
"van-picker": "@vant/weapp/picker/index",
"van-popup": "@vant/weapp/popup/index"
}
}
然后编写date-picker的wxml文件:
<van-popup round show="{{ isShow }}" bind:close="cancel" position="bottom" custom-style="height: 55%">
<van-picker show-toolbar columns="{{ date_time_list }}" bind:cancel="cancel" bind:change="change"
bind:confirm="confirm" />
</van-popup>
因为van-picker的参数columns接受的是一个对象数组,与picker-view有一定差异,所以需要将date-picker的js文件进行如下更改。 1.修改data,增加date_time_list
data: {
isShow: false,
selectDate: "",
dialogh: 0,
date_list: [],
time_list: [],
date_time_list: []
},
2.修改attached函数
let date_time_list = [{
values: date_list
},
{
values: time_list
}
];
this.setData({
date_list: date_list,
time_list: time_list,
date_time_list: date_time_list
})
3.修改change函数
change: function (e) {
let val = e.detail.value;
let select = val[0] + val[1];
this.setData({
selectDate: select
})
},
|