vue3+elementPlus el-date-picker 自定义禁用状态hook 实现结束时间不能小于开始时间

背景:

复制代码
elementPlus的el-date-picker中,相较于了element,升级了写法,
如果为每一个开始时间、结束时间设置禁用状态,在全局中会造成代码冗余。
所以在vue3中采用自定义hook的方式,实现代码复用。

1、实现如下效果:

复制代码
开始时间:今天过后日期不可选,如p1所示;
结束时间:必须大于开始时间,精确到时分秒,如p2所示。

2、编写hook(useDisabledDate.ts)

复制代码
export function useDisabledDate() {
	// 开始时间与结束时间,采用赋值的方式
    const forDisStartTime = ref<Date | string>()
    const forDisEndTime = ref<Date | string>()
    
    // 不可用的开始时间,如图1所示
    const disabledStartTime = (data: Date) => {
        return data.getTime() > new Date().getTime()
    }

    // 结束时间--日期
    const disabledEndTimeDate = (data: Date) => {
        if (forDisStartTime.value) {
            const hours = new Date(forDisStartTime.value).getHours(),
                seconds = new Date(forDisStartTime.value).getSeconds(),
                minutes = new Date(forDisStartTime.value).getMinutes()
            if (hours == 0 && minutes == 0 && seconds == 0) return data.getTime() < new Date(forDisStartTime.value).getTime() - 1000
            else return data.getTime() < new Date(forDisStartTime.value).getTime() - 8.64e7
        }
    }
// 结束时间--时
    const disabledEndTimeHours = () => {
        const hours = new Date(forDisStartTime.value as Date).getHours(),
            sY = new Date(forDisStartTime.value).getFullYear(),
            sM = new Date(forDisStartTime.value).getMonth(),
            sD = new Date(forDisStartTime.value).getDate(),
            eY = new Date(forDisEndTime.value).getFullYear(),
            eM = new Date(forDisEndTime.value).getMonth(),
            eD = new Date(forDisEndTime.value).getDate()
        const arrs = []
        if (sY == eY && sM == eM && sD == eD) {
            for (let i = 0; i < 24; i++) {
                if (hours <= i) continue
                arrs.push(i)
            }
        }
        return arrs
    }
    // 结束时间--分
    const disabledEndTimeMinutes = () => {
        const minutes = new Date(forDisStartTime.value as Date).getMinutes(),
            sY = new Date(forDisStartTime.value).getFullYear(),
            sM = new Date(forDisStartTime.value).getMonth(),
            sD = new Date(forDisStartTime.value).getDate(),
            eY = new Date(forDisEndTime.value).getFullYear(),
            eM = new Date(forDisEndTime.value).getMonth(),
            eD = new Date(forDisEndTime.value).getDate()
        const arrs = []
        if (sY == eY && sM == eM && sD == eD) {
            for (let i = 0; i < 60; i++) {
                if (minutes <= i) continue
                arrs.push(i)
            }
        }
        return arrs
    }
    // 结束时间--秒
    const disabledEndTimeSeconds = () => {
        const seconds = new Date(forDisStartTime.value).getSeconds(),
            sY = new Date(forDisStartTime.value).getFullYear(),
            sM = new Date(forDisStartTime.value).getMonth(),
            sD = new Date(forDisStartTime.value).getDate(),
            eY = new Date(forDisEndTime.value).getFullYear(),
            eM = new Date(forDisEndTime.value).getMonth(),
            eD = new Date(forDisEndTime.value).getDate()
        const arrs = []
        if (sY == eY && sM == eM && sD == eD) {
            for (let i = 0; i < 60; i++) {
                if (seconds <= i) continue
                arrs.push(i)
            }
        }
        return arrs
    }
    return {
        forDisStartTime,
        forDisEndTime,
        disabledStartTime,
        disabledEndTimeDate,
        disabledEndTimeHours,
        disabledEndTimeMinutes,
        disabledEndTimeSeconds
    }
}

3、在.vue文件中使用该hook

复制代码
<script setup lang="ts">
// 引入
import { useDisabledDate } from '@/hooks/useDisabledDate'

const formItem = reactive({
	beginTime: '',
	endTime: ''
})

// #region disabled-date
const {
    forDisStartTime,
    forDisEndTime,
    disabledStartTime,
    disabledEndTimeDate,
    disabledEndTimeHours,
    disabledEndTimeMinutes,
    disabledEndTimeSeconds
} = useDisabledDate()

// 赋值开始时间
watch(
    () => formItem.beginTime,
    (newTime) => {
        forDisStartTime.value = newTime
    },
    { immediate: true }
)
// 赋值结束时间
watch(
    () => formItem.endTime,
    (newTime) => {
        forDisEndTime.value = newTime
    },
    { immediate: true }
)
// #endregion
</script>

<template>
	<el-form :model="formItem" ref="formRef" :rules="formRules" label-width="120px" size="small">
		<el-form-item label="开始时间" prop="beginTime">
		     <el-date-picker
		         v-model="formItem.beginTime"
		         type="datetime"
		         :clearable="false"
		         value-format="YYYY-MM-DD HH:mm:ss"
		         :disabled-date="disabledStartTime"
		     >
		     </el-date-picker>
		 </el-form-item>
		 <el-form-item label="结束时间" prop="endTime">
		     <el-date-picker
		         v-model="formItem.endTime"
		         type="datetime"
		         style="width: 100%"
		         :clearable="false"
		         value-format="YYYY-MM-DD HH:mm:ss"
		         :disabled-date="disabledEndTimeDate"
		         :disabled-hours="disabledEndTimeHours"
		         :disabled-minutes="disabledEndTimeMinutes"
		         :disabled-seconds="disabledEndTimeSeconds"
		     >
		     </el-date-picker>
		 </el-form-item>
	</el-form>
</template>
相关推荐
一拳不是超人7 分钟前
一个没测暗色模式的 Bug,吃掉了我一半 谷歌扩展用户
前端·javascript·程序员
liangshanbo121523 分钟前
React useState 函数式更新面试题整理
前端·react.js·前端框架
涛涛ing28 分钟前
为什么你的页面在 Safari 上总出问题?Interop 2027 正在解决这个 20 年老毛病
前端
不一样的少年_41 分钟前
WebP 压缩到底在干嘛?小白也能看懂的原理拆解
前端·后端·图片资源
问心无愧051342 分钟前
ctf show web 177
前端·笔记
不一样的少年_1 小时前
PNG/JPG 如何变成 WebP?真相不是改后缀!
前端·后端·图片资源
杉氧1 小时前
RN 性能调优指南:重渲染(Re-renders)控制与长列表(FlatList)优化
android·前端·react native
一_个前端1 小时前
[JS] 一站式搞定 PDF、图片、Dom弹窗、表格的浏览器打印功能
前端
JavaGuide1 小时前
阿里 Qoder 又开源了一个专门给 Claude Code、Codex 做“体检”的项目
前端·后端
不一样的少年_1 小时前
JPEG 压缩到底在干嘛?小白也能看懂的 8 步拆解
前端·后端·图片资源