小程序使用的UI组件库是uview,刚开始就是使用的是uview中日历组件,但这个组件有一个缺点,无法选择当前日期之前的日期,百度了一下,说设置 minDate 和 maxDate ,再设置 monthNum 就可以达到效果。但是设置之后第一次打开是正常的,第二次打开就不正常了,要么会闪一下,然后可选日期才可以选历史日期,要么就只能选未来日期。后面就直接去 hbuilder 插件市场下了一个插件,蛮好用的,分享一下:
方法一:uview组件中的日历
<u-calendar
:show="show"
mode="range"
@confirm="confirm"
@close="close"
rowHeight='120'
:minDate="minDate"
:maxDate="maxDate"
:defaultDate="defaultDates"
:monthNum="12"
:round="20"
allowSameDay
></u-calendar>
虽然选择历史日期有点坑,但是如果没有这个需求,用它选择日期还是蛮舒服的,选择历史日期就算了,还是自己封装或者下载插件吧。
方法二:下载插件
首先 hbuilder 插件市场去下载插件,下载插件的位置会自动在这里,如图
页面中引用插件
代码:
<template>
<view class="body">
<view class="search">
<view class="date" @click="getDate">
<view class="text">
<text class="date_text" v-if="!start">开始日期</text>
<text v-if="start">{{start}}</text>
<text class="zhi">至</text>
<text class="date_text" v-if="!end">结束日期</text>
<text v-if="end">{{end}}</text>
</view>
<img src="@/static/image/add/icon-date.png">
</view>
<view class="but" @click="submit()">
<text>查询</text>
</view>
</view>
</view>
<date-range
:mode="viewMode"
:showMutibleDate="showMutibleDate"
:startDate="startDate"
:endDate="endDate" @onSelected="dateSelected"></date-range>
</view>
</template>
<script>
import moment from "moment"
import dateRange from '@/components/zxp-datepickerRange/zxp-datepickerRange.vue'
export default {
components: {
dateRange
},
data() {
return {
endDate:moment().format('YYYY/MM/DD'), // 默认结束时间 YYYY/MM/DD
startDate:moment().format('YYYY/MM/DD'), // 默认开始时间 YYYY/MM/DD
showMutibleDate: false,
viewMode: 'date',
dateValue: '',
timeValue: ''
};
},
mounted() {
},
methods: {
dateSelected(e) {
if (e) {
let start = e.start
let end = e.end
this.startDate = start,
this.endDate = end
this.start = moment(start).format('YYYY/MM/DD');
this.end = moment(end).format('YYYY/MM/DD');
}
this.showMutibleDate = false
},
// 打开时间选择器
getDate(){
this.viewMode = 'date'
this.showMutibleDate = true
},
// 查询
submit(){
console.log('查询结果')
}
},
}
</script>
<
效果图:
插件里我调了一些样式和判断,如z-index、弹出框的高度、开始日期和结束日期比较大小的校验。这个可根据自己的需求进行一些小改动。
最近发现这个插件有一个地方有点魔性,譬如2月30号;针对这,在插件zxp-datepickerRange中做了改动,添加的代码如下:
data() {
const days1 = [] // 一个月31天的数组
const days2 = [] // 一个月30天的数组
const days3 = [] // 二月29天的数组
const days4 = [] // 二月28天的数组
for (let i = 1; i <= 31; i++) {
days1.push(i)
}
for (let i = 1; i <= 30; i++) {
days2.push(i)
}
for (let i = 1; i <= 29; i++) {
days3.push(i)
}
for (let i = 1; i <= 28; i++) {
days4.push(i)
}
return {
days1,
days2,
days3,
days4
};
},
created() {
this.passageStart = this.startDate
this.passageEnd = this.endDate
const now = new Date(this.passageStart)
const YY = now.getFullYear()
var MM = now.getMonth() + 1
// 这里是判断当前月的天数
const yearType1 = ((YY % 4 == 0) && (YY % 100 != 0)) || (YY % 400 == 0) ? 'leap' : 'normal'
if(MM == 4 || MM == 6 || MM == 9 || MM == 11){
this.days = this.days2
} else if (MM == 2 && yearType1 == 'leap'){
this.days = this.days3
} else if(MM == 2 && yearType1 == 'normal'){
this.days = this.days4
} else{
this.days = this.days1
}
},
methods: {
bindMutibleDateChange: function(e) {
console.log('变化了',e.detail.value)
const val = e.detail.value
if (this.mode == 'date') {
let year = this.years[val[0]]
let month = this.months[val[1]]
let day = this.days[val[2]]
// 当时间选择器发生变化时,这里会根据月判断,然后重新渲染天数
// 判断是不是闰年
const yearType = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0) ? 'leap' : 'normal'
if(month == 4 || month == 6 || month == 9 || month == 11){
this.days = this.days2
} else if (month == 2 && yearType == 'leap'){
this.days = this.days3
} else if(month == 2 && yearType == 'normal'){
this.days = this.days4
} else{
this.days = this.days1
}
} else {
......
}
},
}
这样一看,感觉改的也蛮多的,到此解决了每个月都是31天的问题。
插件地址:https://ext.dcloud.net.cn/plugin?id=3825