欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-30 20:34:17
...

日期时间范围选择器

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

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" 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])

组件实试用注意事项

  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问题
相关标签: vue自定义组件