Vue自定义组件之日期时间范围选择器

日期时间范围选择器

该组件 时间选择到分钟,时分的选择支持输入和上下加减调整

在这里插入图片描述

代码分析

<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" @change="changeTimeHandle('start')" 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" @change="changeTimeHandle('start')" 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" @change="changeTimeHandle('end')" 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" @change="changeTimeHandle('end')" 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
                }
            }
        },
        changeTimeHandle(type) {
            let startUnix = moment(`${this.startTime}:00`).unix()
            let endUnix = moment(`${this.endTime}:00`).unix()
            if (endUnix < startUnix) {
                this.$nextTick(() => {
                    if (type === 'start') {
                        ;[this.num3, this.num4] = [this.num1, this.num2]
                    } else {
                        ;[this.num1, this.num2] = [this.num3, this.num4]
                    }
                })
            }
        }
    },
    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>

组件使用(基础组件可进行全局注册,直接使用)

<my-date-times-picker 
	v-model="customTime"
	@change="changeHandle"
></my-date-times-picker>
属性
参数说明类型可选值默认值
v-model绑定值Array
方法
事件名称说明回调参数
change点击确定时触发([startTime,endTime])
组件实试用注意事项
  1. v-mode 绑定时,初始值给定 [] 即可,组件会自动赋初始值(今天的00:00-23:59)
  2. 组件基于 element 用到的组件有:Popover 弹出框 && DatePicker 日期选择器 && InputNumber 计数器 && Button 按钮,使用前请确保以上组件已注册
  3. 组件用到的库: moment
  4. 当该组件需要隐藏时,建议使用v-show(使用v-if影响 v-model的自动赋值)
不足之处
  1. 该组件css想使用 BEM,目前看 很不到位
  2. 该组件时间选择只到分
  3. 作为行块元素,会有margin问题
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值