创建插件seldatetime
// 插件JS部分
Component({
// 一些选项
options: {
// 样式隔离:apply-shared 父影响子,shared父子相互影响, isolated相互隔离
styleIsolation:"isolated",
// 允许多个插槽
multipleSlots: true
},
// 组件的对外属性:在 properties 定义段中,属性名采用驼峰写法(propertyName);在 wxml 中,指定属性值时则对应使用连字符写法(property-name="")
properties: {
// 传递默认选中日期
value: String,
// 最大时间
end: String,
// 最小时间
start: String
},
// 组件的内部数据
data: {
currKey: [],// 当前选中的时间下标
item: [],// 当前选中时间,格式[2023, 12, 22, 10, 8]
list: [],// 时间多列数据集,格式[[], [], [], [], []]
},
// 类似于 mixins 和 traits 的组件间代码复用机制
behaviors: [],
// 组件数据字段监听器,用于监听 properties 和 data 的变化
observers:{},
// 组件间关系定义
relations: {},
// 通过组件的外部类实现父组件控制子自己的样式
externalClasses: [],
// 组件生命周期声明对象
lifetimes: {
attached(){
this._initialize()
},
moved(){},
detached(){}
},
// 组件所在页面的生命周期声明对象
pageLifetimes: {
show(){},
hide(){},
resize(){}
},
/**
* 在组件实例刚刚被创建时执行。
* 组件实例刚刚被创建好时, created 生命周期被触发。此时,组件数据 this.data 就是在 Component 构造器中定义的数据 data。 此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段
*/
created(){},
/**
* 在组件实例进入页面节点树时执行
* 在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行
*/
attached(){},
/**
* 在组件在视图层布局完成后执行
*/
ready(){},
/**
* 在组件实例被移动到节点树另一个位置时执行
*/
moved() {},
/**
* 在组件实例被从页面节点树移除时执行
* 在组件离开页面节点树后, detached 生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发
*/
detached() {},
/**
* 每当组件方法抛出错误时执行
*/
error(){},
/**
* 组件的方法,包括事件响应函数和任意的自定义方法
*/
methods: {
/**
* 自定义初始化方法
*/
_initialize() {
this.setData({
item: this.datetimeStringToArray(this.data.value || this.getCurrDatetime()),
})
this.setDatetimeList()
},
/**
* value 改变时触发 change 事件,event.detail = {value}
*/
changeDatetime(e){
this.triggerEvent('change', {
value: this.datetimeArrayToString(this.data.item)
})
},
/**
* 选择每列时间都会触发
*/
columnChangeDatetime({ detail }){
var column = detail.column;
var value = detail.value;
this.data.item[column] = parseInt(this.data.list[column][value]);
this.setData({
item: this.data.item
})
this.setDatetimeList()
},
/**
* 设置时间列数据集
* @param {*} datetime
*/
setDatetimeList(){
var datetime = this.data.item;
var currYear = new Date().getFullYear();
var startArr = this.datetimeStringToArray(this.data.start || (currYear - 100) + '-01-01 01:01');
var endArr = this.datetimeStringToArray(this.data.end || (currYear + 100) + '-12-31 24:59');
var startStr = startArr.join('');
var endStr = endArr.join('');
var datetimeStr = datetime.join('');
var yearArr = this.getColumnBetweenArray(startArr[0], endArr[0], '年');
// 计算开始月
var startMonth = (datetimeStr.substr(0, 4) <= startStr.substr(0, 4) ? startArr[1] : 1);
// 计算结束月
var endMonth = (datetimeStr.substr(0, 4) >= endStr.substr(0, 4) ? endArr[1] : 12);
var monthArr = this.getColumnBetweenArray(startMonth, endMonth, '月');
// 计算开始日
var startDay = (datetimeStr.substr(0, 6) <= startStr.substr(0, 6) ? startArr[2] : 1);
// 计算每年这个月的天数
var dayCount = new Date(datetime[0], datetime[1], 0).getDate();
// 计算结束日
var endDay = (datetimeStr.substr(0, 6) >= endStr.substr(0, 6) ? endArr[2] : dayCount);
var dayArr = this.getColumnBetweenArray(startDay, endDay, '日');
// 计算开始小时
var startHour = (datetimeStr.substr(0, 8) <= startStr.substr(0, 8) ? startArr[3] : 1);
// 计算结束小时
var endHour = (datetimeStr.substr(0, 8) >= endStr.substr(0, 8) ? endArr[3] : 24);
var hourArr = this.getColumnBetweenArray(startHour, endHour, '时');
// 计算开始分钟
var startMinute = (datetimeStr.substr(0, 10) <= startStr.substr(0, 10) ? startArr[4] : 1);
// 计算结束分钟
var endMinute = (datetimeStr.substr(0, 10) >= endStr.substr(0, 10) ? endArr[4] : 59);
var minuteArr = this.getColumnBetweenArray(startMinute, endMinute, '分');
// 计算当前时间的下标
var yearKey = this.getKey(yearArr, datetime[0]);
var monthKey = this.getKey(monthArr, datetime[1])
var dayKey = this.getKey(dayArr, datetime[2])
var hourKey = this.getKey(hourArr, datetime[3])
var minuteKey = this.getKey(minuteArr, datetime[4])
this.setData({
currKey: [yearKey, monthKey, dayKey, hourKey, minuteKey],
list: [yearArr, monthArr, dayArr, hourArr, minuteArr],
item: [parseInt(yearArr[yearKey]), parseInt(monthArr[monthKey]), parseInt(dayArr[dayKey]), parseInt(hourArr[hourKey]), parseInt(minuteArr[minuteKey])]
})
},
/**
* 获取数值之间数据列表
* @param {*} start
* @param {*} end
*/
getColumnBetweenArray(start, end, unit){
var resArray = [];
for(var i = start;i <= end; i++){
resArray.push(this.zeroize(i) + unit);
}
return resArray;
},
/**
* 获取KEY
* @param {*} array
* @param {*} item
*/
getKey(array, item){
var key = array.findIndex(value => parseInt(item) == parseInt(value));
if(key === -1){
return 0;
}
return key;
},
/**
* 补零
* @param {*} number
*/
zeroize(number){
return number < 10 ? '0' + number : number;
},
/**
* 获取当前时间
*/
getCurrDatetime(){
var d = new Date();
var year = d.getFullYear()
var month = d.getMonth() + 1
var day = d.getDate();
var hours = d.getHours()
var minutes = d.getMinutes()
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes;
},
/**
* 时间字符串转数组
* @param {*} datetime
*/
datetimeStringToArray(datetime){
return datetime.replace(/-|:/g, ' ').split(' ').map(item => parseInt(item));
},
/**
* 时间数组转字符串
* @param {*} datetime
*/
datetimeArrayToString(datetime){
return datetime[0] + '-' + datetime[1] + '-' + datetime[2] + ' ' + datetime[3] + ':' + datetime[4]
}
},
})
// wxml部分
<picker mode="multiSelector" range="{{ list }}" value="{{ currKey }}" bindchange="changeDatetime" bindcolumnchange="columnChangeDatetime">
<slot></slot>
</picker>
app.json配置
"usingComponents": {
"d-demo": "../../components/seldatetime/index"
},
page页面中调用
// wxml文件内容
<d-demo value="{{ value }}" start="2020-01-01 05:20" end="2060-12-30 18:51" bindchange="selectDatetime">
<input value="{{ value }}" placeholder="请选择时间" style="border: 1px solid #e2e2e2;padding: 10px;border-radius: 5px;" />
</d-demo>
// JS文件内容
Page({
/**
* 页面的初始数据
*/
data: {
value: '2023-12-22 16:50',
},
/**
* 选择时间
*/
selectDatetime(e){
var d = e.detail
this.setData({
value: d.value
})
}
})