如果小程序中有可复用的UI且具有一定的功能性,就可以使用自定义组件将其封装起来。(如果仅仅只需要复用UI可使用template)
我还算一个小程序的新手,自己看到处都是坑的官方文档,不得不说,腾讯官方的技术人员自认为自己很强(或许也很强),给出的文档很多东西都是莫名其妙的定义,和一些粗糙的案例,剩下的都靠程序员自己去揣测和实验,白白浪费时间。
好吧,这个方法是我看了网上一些前辈朋友给出的案例,研究了一番,写了两天才搞出来的。没办法,TMD的官方文档太扯了,要不停地实验测试。
先看效果:
未标题-1.jpg
自定义组件代码
小程序根目录下建components->date-time-picker文件夹:
## date-time-picker.json
{
"component": true,
"usingComponents": {}
}
## date-time-picker.wxml
<picker mode="multiSelector" class="{{className}}" name="{{name}}" value="{{multiSelectdArray}}" range="{{multiDateTime}}" bindcolumnchange="handleColumnChange" bindchange="handleValueChange" bindcancel="handleCancel">
<slot></slot>
</picker>
### date-time-picker.js
// component/date-time-picker/date-time-picker.js
Component({
options: {
styleIsolation: 'apply-shared' //调用页面控制组件样式
},
properties: {
name: String,
className: String,
startYear: String,
endYear: String,
value: String
},
/**
* 组件的初始数据
*/
data: {
multiArray:[],
multiSelectdArray: [0, 0, 0, 0, 0],
},
observers: {
},
ready: function(e) {
this._formDateTime();
},
/**
* 组件的方法列表
*/
methods: {
//格式化日期
_formDateTime(){
// 默认开始显示数据
var nowDateTime = this.properties.value ? [...this.properties.value.split(' ')[0].split('-'), ...this.properties.value.split(' ')[1].split(':')] : this._getNewDateArry();
var multiDateTime = [[],[],[],[],[]];
var startYear = this.properties.startYear || nowDateTime[0];
var endYear = this.data.properties || parseInt(nowDateTime[0]) + 1;
// 处理联动列表数据
/* 年月日 时分秒 */
multiDateTime[0] = this._getLoopArray(startYear, endYear, '年');
multiDateTime[1] = this._getLoopArray(1, 12, '月');
multiDateTime[2] = this._getMonthDay(nowDateTime[0], nowDateTime[1], '日');
multiDateTime[3] = this._getLoopArray(0, 23, '时');
multiDateTime[4] = this._getLoopArray(0, 59, '分');
// multiDateTime[5] = this._getLoopArray(0, 59, '秒');
var multiSelectdArray = this._getMultiSelectdArray(multiDateTime, nowDateTime);
this.setData({
multiDateTime: multiDateTime,
multiSelectdArray: multiSelectdArray,
});
},
/* 查询选中状态数组 */
_getMultiSelectdArray(multiDateTime, nowDateTime){
let multiSelectdArray = this.data.multiSelectdArray;
for (let i in multiDateTime) {
for (let k in multiDateTime[i]) {
var a = multiDateTime[i][k];
if(a.replace(/[\u4e00-\u9fa5]/g, '') == nowDateTime[i]){
multiSelectdArray[i] = k;
}
}
}
return multiSelectdArray;
},
/* 获取起始数组 */
_getLoopArray(start, end, name){
var name = name || '';
var start = start || 0;
var end = end || 1;
var array = [];
for (var i = start; i <= end; i++) {
array.push(this._withData(i) + name);
}
return array;
},
/* 获取每月天数 */
_getMonthDay(year, month, name){
var name = name || 0;
var flag = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0), array = null;
switch (month) {
case '01':
case '03':
case '05':
case '07':
case '08':
case '10':
case '12':
array = this._getLoopArray(1, 31, name)
break;
case '04':
case '06':
case '09':
case '11':
array = this._getLoopArray(1, 30, name)
break;
case '02':
array = flag ? this._getLoopArray(1, 29, name) : this._getLoopArray(1, 28, name)
break;
default:
array = '月份格式不正确,请重新输入!'
}
return array;
},
/* 获取当前时间 */
_getNewDateArry(){
// 当前时间的处理
var newDate = new Date();
var year = this._withData(newDate.getFullYear()),
mont = this._withData(newDate.getMonth() + 1),
date = this._withData(newDate.getDate()),
hour = this._withData(newDate.getHours()),
minu = this._withData(newDate.getMinutes());
// seco = this._withData(newDate.getSeconds());
return [year, mont, date, hour, minu];
},
_stringToDate(str) {
str = str.replace(/-/g, "/");
return new Date(str);
},
/* 数据左边加0 */
_withData(param){
return param < 10 ? '0' + param : '' + param;
},
/* 切换时间 */
handleColumnChange(e) {
var multiSelectdArray = this.data.multiSelectdArray;
if(e.detail.column <= 1){
var multiDateTime = this.data.multiDateTime;
var year = this.data.multiArray[multiSelectdArray[0]];
var month = this._withData(e.detail.value + 1);
multiDateTime[2] = this._getMonthDay(year, month, '日');
this.setData({
multiDateTime: multiDateTime
});
}
this.setData({
multiSelectdArray: multiSelectdArray
});
},
/* 改变picker值 */
handleValueChange(e){
var _this = this;
let dateArr = [], multiSelectdArray = [];
for (let i in e.detail.value) {
let v = _this.data.multiDateTime[i][e.detail.value[i]];
v = v.replace(/[\u4e00-\u9fa5]/g, '');
multiSelectdArray.push(e.detail.value[i]);
dateArr.push(v.toString());
}
_this.setData({
multiSelectdArray: multiSelectdArray //设置下拉选中状态
});
let defaultDateTime = dateArr[0] + "-" + dateArr[1] + "-" + dateArr[2] + " " + dateArr[3] + ":" + dateArr[4];
_this.triggerEvent('change', {
date: defaultDateTime
})
},
/* 取消 */
handleCancel(e){
_this.triggerEvent('cancel', {
})
}
}
})
使用方法
1、在app.json中添加一个测试路径:
"pages":[
"pages/test/index",
],
小程序开发工具会自动生成四个文件:
/pages/test/index.wxml
/pages/test/index.wxss
/pages/test/index.js
/pages/test/index.json
2、在json文件中引入自定义组件,代码如下:
{
"usingComponents": {
"date-time-picker": "/components/date-time-picker/date-time-picker"
}
}
3、wxml中引入组件:
## value 默认时间
## startYear 起始年份
## endYear 结束年份
## handleChange picker选定后执行的程序名称
<date-time-picker value="{{value}}" startYear="2019" endYear="2020" bind:change="handleChange">时间:{{value}}</date-time-picker>
4、js代码
// pages/test/index.js
Page({
/**
* 页面的初始数据
*/
data: {
value: "2020-12-31 15:11"
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
handleChange(e) {
console.log(e)
this.setData({
value: e.detail.date
})
},
})
以上是就是全部代码了,可以直接使用,如果有BUG存在,还请留言提醒。
这个日期时间组件选定格式为 YYYY-MM-DD HH:ii,精确到分钟,因为精确到秒的用途不大,如果需要用到秒,只需要到组件date-time-picker.js中略微修改一下,把秒注释部分删除,增加multiArray,multiSelectdArray的长度就行了。