微信小程序的双时间选择器基于picker的mode = multiSelector
废了好大的劲写了这么一个组件,叉会腰~
其实这段代码并不精炼,不过本人也是个刚工作一年多的小菜鸟,就先放在这里,有想法再来改;
事实上我就在写这篇博文的时候,就修改了3个bug,就当给大家提供一个思路吧;
想到啥写啥,我觉得这么写比用picker-view的好处就是可以使用原生组件,只需要管自己想管的逻辑,不过写完发现逻辑部分好鸡儿多;
我认为这个组件主要的缺点在于每次滚动事件都重新计算年月日,如果能一次计算清楚年月日,只管显示,想必会简单不少,不过本人简单想了想没找到思路,就留待大神们解决啦;
由于我用的mpx框架,这段代码不能直接插入到原生小程序里,需要修改
html部分:
<picker
mode="multiSelector"
bindchange="bindMultiPickerChange"
bindcolumnchange="bindMultiPickerColumnChange"
value="{{multiIndex}}"
range="{{multiArray}}"
>
时间
</picker>
js部分:
<script>
//再次说明本人使用的是mpx框架,这段代码不能直接插入到小程序里,需要修改
//onLoad和onShow都没反应,就写到了这里
const date = new Date();
const years = [];
const months = [];
const days = [];
const years2 = [];
const months2 = [];
const days2 = [];
const yearIndex = date.getFullYear()-2010
const monthIndex = date.getMonth()
const dayIndex = date.getDate() - 1
//获取年 i是起始年份, i<=结束年份(当前年份+5)
for (let i = 2010; i <= date.getFullYear() + 5 ; i++) {
years.push("" + i);
}
//获取月份
for (let i = 1; i <= 12; i++) {
if (i < 10) {
i = "0" + i;
}
months.push("" + i);
}
//获取日期
for (let i = 1; i <= 31; i++) {
if (i < 10) {
i = "0" + i;
}
days.push("" + i);
}
//获取第二行年份
for (let i = date.getFullYear(); i <= date.getFullYear() + 5 ; i++) {
years2.push("" + i);
}
//获取第二行月份
for (let i = date.getMonth()+1; i <= 12; i++) {
if (i < 10) {
i = "0" + i;
}
months2.push("" + i);
}
//获取第二行日期
for (let i = date.getDate(); i <= 31; i++) {
if (i < 10) {
i = "0" + i;
}
days2.push("" + i);
}
createComponent({
data:{
time: '',
multiArray: [years, months, days,"-", years2, months2, days2],
multiIndex: [yearIndex,monthIndex , dayIndex,0, 0, 0,0],
},
methods: {
bindMultiPickerChange(e) {
// console.log('picker发送选择改变,携带值为', e.detail.value)
this.multiIndex = e.detail.value
const index = this.multiIndex
const year = this.multiArray[0][index[0]]
const month = this.multiArray[1][index[1]]
const day = this.multiArray[2][index[2]]
const year2 = this.multiArray[4][index[4]]
const month2 = this.multiArray[5][index[5]]
const day2 = this.multiArray[6][index[6]]
this.time = year + '-' + month + '-' + day + ' 至 ' + year2 + '-' + month2 + '-' + day2
console.log(this.time)
this.triggerE()
},
//监听picker的滚动事件, TUDO 这个组件可能还有bug,需要测试大哥的努力了
bindMultiPickerColumnChange(e) {
//获取年份
const column = e.detail.column
const array = this.multiArray //例 array[0][index[0]] 代表开始年份的值 array[0]代表开始年份列表
const index = this.multiIndex // index[0] 代表开始年份的下标
this.multiIndex[column] = e.detail.value
// console.log('修改的列为',column, ',值为', e.detail.value);
if(column == 0){
//修改开始年份需要同步更新结束年份列表,为了不出现显示bug,还得同步更新点开始日期列表
this.multiArray[2] = this.getday(1,array[1][index[1]],array[0][index[0]])
this.multiArray[4] = this.getyear(array[0][index[0]])
if(array[4].length<=index[4]){//如果结束年份列表长度不足,显示列表头
this.multiIndex[4] = 0
}
if(array[1][index[1]] == array[5][index[5]]){ //如果月份相同,同步结束日期列表
this.multiArray[6] = this.getday(index[2]+1,array[5][index[5]],array[4][index[4]])
}
}else if(column == 4){
//修改结束年份需要修改 结束日期列表 和 结束月份列表,如果 开始年份和结束年份 一致,开始月份不能小于结束月份,
if(array[0][index[0]] == array[4][index[4]] && array[1][index[1]] > array[5][index[5]]){
this.multiArray[5] = this.getmonth(index[1]+1)
if(array[1][index[1]] >= array[5][index[5]]){ //修改了结束月份列表后,判断结束日期列表如何修改
this.multiArray[6] = this.getday(index[2]+1,array[5][index[5]],array[4][index[4]])
}else{
this.multiArray[6] = this.getday(1,array[5][index[5]],array[4][index[4]])
}
}else{ //如果开始年份小于结束年份,需要显示所有月份和所有日期
this.multiArray[5] = this.getmonth()
this.multiArray[6] = this.getday(1,array[5][index[5]],array[4][index[4]])
}
}else if(column == 1 || column == 5 ){ //月份发生改变,响应的日期列表也要改变
this.multiArray[column+1] = this.getday(1,array[column][index[column]],array[column-1][index[column-1]])
//年份相同的时候,开始月份不能大于结束月份
if(array[0][index[0]] == array[4][index[4]] ){
let monthi = parseInt(array[1][index[1]])
this.multiArray[5] = this.getmonth(monthi)
if(array[5].length<=index[5]){//如果结束月份列表长度不足,显示列表头
this.multiIndex[5] = 0
}
//判断一下月份,不判断下标是因为两个列表的长度很可能不同
let value = array[column][index[column]]
if((value == 4 || value == 6 || value == 9 || value == 11) && index[column+1] == 30 ){
this.multiIndex[2] = 29
this.multiIndex[6] = 29
}else if(value == 2 && index[column+1] > 27){
this.multiIndex[2] = 27
this.multiIndex[6] = 27
}
//修改结束日期列表
if(array[1][index[1]] == array[5][index[5]]){
this.multiArray[6] = this.getday(array[2][index[2]],array[5][index[5]],array[4][index[4]])
}
}
}else if(column == 2 && array[0][index[0]] == array[4][index[4]] && array[1][index[1]] == array[5][index[5]]){
//如果年份和月份都相同,同步结束日期,日期上滑也得同步,否则就得再定位array[6][index[6]]
this.multiArray[6] = this.getday(array[2][index[2]],array[1][index[1]],array[0][index[0]])
if(array[6].length<=index[6]){//如果结束日期列表长度不足,显示列表头
this.multiIndex[6] = 0
}
}
},
getyear(e){
let year = e?e:2010
let years = []
for (let i = year; i <= new Date().getFullYear() + 5 ; i++) {
years.push("" + i);
}
return years
},
getmonth(e){
let month = e?e:1
let months = []
for (let i = month; i <= 12; i++) {
if (i < 10) {
i = "0" + i;
}
months.push("" + i);
}
return months
},
getday(d,m,y){
let dm = 31
if (m == 4 || m == 6 || m == 9 || m == 11){
dm = 30
if(d == 31){
d = 30
}
}else if( m == 2 ){
if(y % 400 == 0 || ( y % 4 == 0 || y % 100 != 0)){
dm = 29
}else{
dm = 28
}
if(d > dm){
d = dm
}
}
let days = []
for (let i = d; i <= dm; i++) {
if (i < 10 &&i.length ===1) {
i = "0" + i;
}
days.push("" + i);
}
return days
},
}
})
</script>
json部分: //再次在这里说明我使用的是mpx框架,和原生不太一样
<script type="application/json">
{
"component": true
}
</script>
css部分没有
ps:写这篇博文的时候才发现自己的第一篇博文没发出去…
时过境迁,拿来放到原生小程序上才发现,wx.setData好恶心…而且代码里还有几个小bug
又时过境迁,找不到上套代码了,只能来拿原生的改
data: {
listdata: [],
time: [],
multiArray: [
[],
[],
[], "-", [],
[],
[]
],
multiIndex: [],
oldDate: [0, 0, 0]
},
getThisDate() {
let date = new Date(); //获取完整的年份(4位,1970-????)
let year = date.getFullYear()
let month = date.getMonth()
let day = date.getDate()
let lists = [year - 2010, month, 0, 0, 0, 0, 0]
let years = this.getyear(2010)
let months = this.getmonth(1)
let days = this.getday(1)
let years2 = this.getyear(year)
let months2 = this.getmonth(month + 1)
let days2 = this.getday(day, month, year)
this.setData({
oldDate: [year, month + 1, day],
multiIndex: lists,
multiArray: [years, months, days, "-", years2, months2, days2]
})
let e = {
detail: {
value: lists
}
}
this.bindMultiPickerChange(e)
},
bindMultiPickerChange(e) {
// console.log('picker发送选择改变,携带值为', e.detail.value)
const index = this.data.multiIndex
const year = this.data.multiArray[0][index[0]]
const month = this.data.multiArray[1][index[1]]
const day = this.data.multiArray[2][index[2]]
const year2 = this.data.multiArray[4][index[4]]
const month2 = this.data.multiArray[5][index[5]]
const day2 = this.data.multiArray[6][index[6]]
this.setData({
multiIndex: e.detail.value,
time: [year + '-' + month + '-' + day, year2 + '-' + month2 + '-' + day2]
})
this.getData()
},
//监听picker的滚动事件, TUDO 这个组件可能还有bug,需要测试大哥的努力了
bindMultiPickerColumnChange(e) {
//获取年份
const column = e.detail.column
const array = this.data.multiArray //例 array[0][index[0]] 代表开始年份的值 array[0]代表开始年份列表
const index = this.data.multiIndex // index[0] 代表开始年份的下标
const oldDate = this.data.oldDate
let up = "multiIndex[" + column + "]";
this.setData({
[up]: e.detail.value
})
// console.log('修改的列为',column, ',值为', e.detail.value);
if (column == 0) {
//修改开始年份需要同步更新结束年份列表,还得同步更新点开始日期列表
let ma2 = "multiArray[2]"
let ma4 = "multiArray[4]"
let mi4 = "multiIndex[4]"
this.setData({
[ma2]: this.getday(1, array[1][index[1]], array[0][index[0]]),
[ma4]: this.getyear(array[0][index[0]])
})
let _index4 = index[4]
let _num4 = 0
_num4 = oldDate[0] - array[0][index[0]]
_index4 += _num4
if (_index4 < 0) _index4 = 0
let old0 = "oldDate[0]"
this.setData({
[old0]: array[0][index[0]],
[mi4]: _index4
})
if (array[4].length <= index[4]) { //如果结束年份列表长度不足,显示列表头
this.setData({
[mi4]: 0
})
}
if (array[1][index[1]] == array[5][index[5]]) { //如果月份相同,同步结束日期列表
let ma6 = "multiArray[6]";
this.setData({
[ma6]: this.getday(index[2] + 1, array[5][index[5]], array[4][index[4]])
})
}
} else if (column == 4) {
//修改结束年份需要修改 结束日期列表 和 结束月份列表,如果 开始年份和结束年份 一致,开始月份不能小于结束月份,
let ma5 = "multiArray[5]";
let ma6 = "multiArray[6]";
let _data5 = ""
let _data6 = ""
if (array[0][index[0]] == array[4][index[4]] && array[1][index[1]] > array[5][index[5]]) {
_data5 = this.getmonth(index[1] + 1)
if (array[1][index[1]] >= array[5][index[5]]) { //修改了结束月份列表后,判断结束日期列表如何修改
_data6 = this.getday(index[2] + 1, array[5][index[5]], array[4][index[4]])
} else {
_data6 = this.getday(1, array[5][index[5]], array[4][index[4]])
}
this.setData({
[ma5]: _data5,
[ma6]: _data6
})
} else { //如果开始年份小于结束年份,需要显示所有月份和所有日期
_data5 = this.getmonth()
_data6 = this.getday(1, array[5][index[5]], array[4][index[4]])
}
this.setData({
[ma5]: _data5,
[ma6]: _data6
})
} else if (column == 1 || column == 5) { //月份发生改变,响应的日期列表也要改变
let mi5 = "multiIndex[5]";
let old1 = "oldDate[1]"
if (column == 1) {
let _index5 = index[5]
let _num5 = 0
_num5 = oldDate[1] - array[1][index[1]]
_index5 += _num5
if (_index5 < 0) _index5 = 0
this.setData({
[old1]: array[1][index[1]],
[mi5]: _index5
})
}
let _index = column + 1
let mai = "multiArray[" + _index + "]";
console.log(mai);
console.log(this.getday(1, array[column][index[column]], array[column - 1][index[column - 1]]));
this.setData({
[mai]: this.getday(1, array[column][index[column]], array[column - 1][index[column - 1]])
})
//年份相同的时候,开始月份不能大于结束月份
if (array[0][index[0]] == array[4][index[4]]) {
let monthi = parseInt(array[1][index[1]])
let ma5 = "multiArray[5]";
this.setData({
[ma5]: this.getmonth(monthi)
})
if (array[5].length <= index[5]) { //如果结束月份列表长度不足,显示列表头
this.setData({
[mi5]: 0
})
}
//判断一下月份,不判断下标是因为两个列表的长度很可能不同
let value = array[column][index[column]]
let mi2 = "multiIndex[2]";
let mi6 = "multiIndex[6]";
let _datai2 = this.data.multiIndex[2]
let _datai6 = this.data.multiIndex[6]
if ((value == 4 || value == 6 || value == 9 || value == 11) && index[column + 1] == 30) {
_datai2 = 29
_datai6 = 29
} else if (value == 2 && index[column + 1] > 27) {
_datai2 = 27
_datai6 = 27
}
this.setData({
[mi2]: _datai2,
[mi6]: _datai6
})
//修改结束日期列表
if (array[1][index[1]] == array[5][index[5]]) {
let ma6 = "multiArray[6]";
this.setData({
[ma6]: this.getday(array[2][index[2]], array[5][index[5]], array[4][index[4]])
})
}
}
} else if (column == 2 && array[0][index[0]] == array[4][index[4]] && array[1][index[1]] == array[5][index[5]]) {
//如果年份和月份都相同,同步结束日期,日期上滑也得同步,否则就得再定位array[6][index[6]]
let ma6 = "multiArray[6]";
let mi6 = "multiIndex[6]";
let old2 = "oldDate[2]"
let _index6 = index[6]
let _num6 = 0
_num6 = oldDate[2] - array[2][index[2]]
_index6 += _num6
if (_index6 < 0) _index6 = 0
this.setData({
[old2]: array[2][index[2]],
[ma6]: this.getday(array[2][index[2]], array[1][index[1]], array[0][index[0]]),
[mi6]: _index6
})
if (array[6].length <= index[6]) { //如果结束日期列表长度不足,显示列表头
let mi6 = "multiIndex[6]";
this.setData({
[mi6]: 0
})
}
}
},
getyear(e) {
let year = e || 2010
let years = []
for (let i = year; i <= new Date().getFullYear() + 5; i++) {
years.push("" + i);
}
return years
},
getmonth(e) {
let month = e || 1
let months = []
for (let i = month; i <= 12; i++) {
if (i < 10) {
i = "0" + i;
}
months.push("" + i);
}
return months
},
getday(d, m, y) {
let dm = 31
if (m == 4 || m == 6 || m == 9 || m == 11) {
dm = 30
if (d == 31) {
d = 30
}
} else if (m == 2) {
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) {
dm = 29
} else {
dm = 28
}
if (d > dm) {
d = dm
}
}
let days = []
for (let i = d; i <= dm; i++) {
if (i < 10 && i.length === 1) {
i = "0" + i;
}
days.push("" + i);
}
return days
},