如果小程序中有可復用的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的長度就行了。