Vue自定义组件之日期时间范围选择器
程序员文章站
2022-05-30 20:34:17
...
日期时间范围选择器
该组件 时间选择到分钟,时分的选择支持输入和上下加减调整
代码分析
<template>
<div class="date-times-picker">
<el-popover placement="bottom" width="460" trigger="click" v-model="visible" @after-leave="hideHandle">
<div class="date-times-picker-box">
<div class="date-times-line">
<span class="date-times-line__label flex-none">开始时间:</span>
<el-date-picker class="date-times-line__date flex-none" :clearable="false" :picker-options="pickerOptions" @change="changeDateHandle('start')" value-format="yyyy-MM-dd" v-model="date1" type="date" placeholder="选择日期" size="medium">
</el-date-picker>
<el-input-number v-model="num1" size="medium" controls-position="right" :min="0" :max="23" class="mar-l-10 date-times-line__ms flex-none"></el-input-number>
<el-input-number v-model="num2" size="medium" controls-position="right" :min="0" :max="59" class="mar-l-10 date-times-line__ms flex-none"></el-input-number>
</div>
<div class="date-times-line">
<span class="date-times-line__label flex-none">结束时间:</span>
<el-date-picker class="date-times-line__date flex-none" :clearable="false" :picker-options="pickerOptions" @change="changeDateHandle('end')" value-format="yyyy-MM-dd" v-model="date2" type="date" placeholder="选择日期" size="medium">
</el-date-picker>
<el-input-number v-model="num3" controls-position="right" :min="0" :max="23" size="medium" class="mar-l-10 date-times-line__ms flex-none"></el-input-number>
<el-input-number v-model="num4" controls-position="right" :min="0" :max="59" size="medium" class="mar-l-10 date-times-line__ms flex-none"></el-input-number>
</div>
<div class="date-times-line__submitbox">
<el-button type="primary" size="medium" @click="submit">确定</el-button>
</div>
</div>
<el-button slot="reference" size="small">{{displayDate}}</el-button>
</el-popover>
</div>
</template>
<script>
export default {
name: 'MyDateTimesPicker',
props: {
value: Array,
},
data() {
return {
date1: '',
date2: '',
num1: 10,
num2: 10,
num3: 23,
num4: 59,
visible: false,
pickerOptions: {
disabledDate(time) {
return (
// 默认只能选择一年
moment(time).format('YYYY-MM-DD') >
moment().format('YYYY-MM-DD') ||
moment(time).format('YYYY-MM-DD') <
moment()
.subtract(1, 'years')
.format('YYYY-MM-DD')
)
}
}
}
},
methods: {
submit() {
let retDates = [`${this.startTime}`, `${this.endTime}`]
this.$emit('input', retDates)
this.$nextTick(() => {
this.$emit('change', retDates)
})
this.visible = false
},
inintDate() {
let retDates = [
moment().format('YYYY-MM-DD 00:00'),
moment().format('YYYY-MM-DD 23:59')
]
this.$emit('input', retDates)
},
hideHandle() {
this.date1 = this.value[0].slice(0, 10)
this.num1 = Number(this.value[0].slice(11, 13))
this.num2 = Number(this.value[0].slice(14, 16))
this.date2 = this.value[1].slice(0, 10)
this.num3 = Number(this.value[1].slice(11, 13))
this.num4 = Number(this.value[1].slice(14, 16))
},
changeDateHandle(type) {
let startUnix = moment(`${this.startTime}:00`).unix()
let endUnix = moment(`${this.endTime}:00`).unix()
if (endUnix < startUnix) {
//结束时间小于开始时间
switch (type) {
case 'start':
;[this.date2, this.num3, this.num4] = [
this.date1,
'23',
'59'
]
break
case 'end':
;[this.date1, this.num1, this.num2] = [
this.date2,
'0',
'0'
]
break
}
} else if (endUnix - startUnix > 30 * 24 * 60 * 60) {
switch (type) {
case 'start':
;[this.date2, this.num3, this.num4] = [
moment
.unix(startUnix)
.add(1, 'M')
.format('YYYY-MM-DD'),
this.num1,
this.num2
]
break
case 'end':
;[this.date1, this.num1, this.num2] = [
moment
.unix(endUnix)
.subtract(1, 'M')
.format('YYYY-MM-DD'),
this.num3,
this.num4
]
break
}
}
}
},
computed: {
startTime() {
return `${this.date1} ${
this.num1 > 9 ? this.num1 : `0${this.num1}`
}:${this.num2 > 9 ? this.num2 : `0${this.num2}`}`
},
endTime() {
return `${this.date2} ${
this.num3 > 9 ? this.num3 : `0${this.num3}`
}:${this.num4 > 9 ? this.num4 : `0${this.num4}`}`
},
displayDate() {
if (!this.value.length) {
//若传入 []
this.inintDate()
return ''
} else {
this.date1 = this.value[0].slice(0, 10)
this.num1 = Number(this.value[0].slice(11, 13))
this.num2 = Number(this.value[0].slice(14, 16))
this.date2 = this.value[1].slice(0, 10)
this.num3 = Number(this.value[1].slice(11, 13))
this.num4 = Number(this.value[1].slice(14, 16))
return this.value.join(' - ')
}
}
}
}
</script>
<style scoped>
.date-times-picker {
display: inline-block;
}
.date-times-picker-box {
padding: 20px 30px;
}
.date-times-line {
display: flex;
margin-top: 10px;
}
.date-times-line__label {
width: 72px;
line-height: 35px;
}
.date-times-line__date {
width: 135px;
}
.date-times-line__ms {
width: 85px;
}
.date-times-line__submit {
display: block;
margin-top: 10px;
}
.date-times-line__submitbox {
display: flex;
justify-content: flex-end;
margin-top: 20px;
}
.flex-none {
flex: none;
}
</style>
组件使用(基础组件可进行全局注册,直接使用)
<ym-date-times-picker
v-model="customTime"
@change="changeHandle"
></ym-date-times-picker>
属性
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
v-model | 绑定值 | Array | – | – |
方法
事件名称 | 说明 | 回调参数 |
---|---|---|
change | 点击确定时触发 | ([startTime,endTime]) |
组件实试用注意事项
- v-mode 绑定时,初始值给定 [] 即可,组件会自动赋初始值(今天的00:00-23:59)
- 组件基于 element 用到的组件有:Popover 弹出框 && DatePicker 日期选择器 && InputNumber 计数器 && Button 按钮,使用前请确保以上组件已注册
- 组件用到的库: moment
- 当该组件需要隐藏时,建议使用v-show(使用v-if影响 v-model的自动赋值)
不足之处
- 该组件css想使用 BEM,目前看 很不到位
- 该组件时间选择只到分
- 作为行块元素,会有margin问题