基于 Vue 3 + Element Plus自定义时间范围选择组件使用教程
作者:JaysonJin
本文介绍了一个基于Vue 3和Element Plus的自定义时间范围选择组件,该组件提供双向绑定的开始时间和结束时间选择,支持常用快捷选项,对vue elementplus时间范围选择组件相关知识感兴趣的朋友一起看看吧
🕓 自定义时间范围选择组件使用教程(基于 Vue 3 + Element Plus)
✅ 一个灵活实用的时间范围选择器,支持开始时间、结束时间、快捷时间选项、本地双向绑定、插槽扩展等功能。
📘 一、功能介绍
该组件基于 Element Plus
的 <el-date-picker>
和 <el-select>
封装,支持以下特性:
v-model:startTime
和v-model:endTime
双向绑定;- 常用时间快捷选项:今天、昨天、本月、上月等;
- 自定义插槽
before
,可拓展前置内容; - 自动识别当前选择是否为快捷项并高亮;
- 支持国际化
$t()
; - 可自定义初始选中项;
- 样式美观、可无缝集成至查询表单。
🧱 二、组件源码
📂 components/TimeSeparation.vue
<template>
<template> <slot name="before" /> <el-date-picker class="timeSeparationClassStart" style="width:160px" v-model="startTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" :default-time="new Date(2000, 1, 1, 0, 0, 0)" /> <span class="timeSeparationClassCenter">-</span> <el-date-picker class="timeSeparationClassEnd" style="width:160px" v-model="endTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" :default-time="new Date(2000, 1, 1, 23, 59, 59)" /> <el-select v-model="dateRangeType" class="timeSeparationClass_after" style="width:100px" @change="changeDateRange"> <el-option v-for="dict in dateList" :key="dict.value" :label="$t(dict.label)" :value="dict.value" /> </el-select> </template>
<script setup>
<script setup> import { useVModel } from '@vueuse/core' import i18n from '@/i18n' import { parseTime } from '@/utils/ruoyi' const emit = defineEmits(['update:startTime', 'update:endTime', 'change']) const props = defineProps({ startTime: String, endTime: String, defaultTime: Number, // 默认快捷选中类型 showAfter: { type: Boolean, default: true } }) // 双向绑定 const startTime = useVModel(props, 'startTime', emit) const endTime = useVModel(props, 'endTime', emit) const dateRangeType = ref(props.defaultTime) function changeDateRange(e) { switch (e) { case 1: setDaysAgo(7); break; case 2: setThisMonth(); break; case 4: setToday(); break; case 5: setYesterday(); break; case 6: setLastMonth(); break; } } // 日期处理 function setDaysAgo(days) { const now = new Date(); const start = new Date(now) start.setDate(start.getDate() - (days - 1)) start.setHours(0, 0, 0, 0) now.setHours(23, 59, 59, 999) startTime.value = parseTime(start) endTime.value = parseTime(now) } function setToday() { const now = new Date(); const start = new Date(now) start.setHours(0, 0, 0, 0) now.setHours(23, 59, 59, 999) startTime.value = parseTime(start) endTime.value = parseTime(now) } function setYesterday() { const start = new Date() const end = new Date() start.setDate(start.getDate() - 1) end.setDate(end.getDate() - 1) start.setHours(0, 0, 0, 0) end.setHours(23, 59, 59, 999) startTime.value = parseTime(start) endTime.value = parseTime(end) } function setThisMonth() { const now = new Date() const start = new Date(now.getFullYear(), now.getMonth(), 1) const end = new Date(now.getFullYear(), now.getMonth() + 1, 0) end.setHours(23, 59, 59, 999) startTime.value = parseTime(start) endTime.value = parseTime(end) } function setLastMonth() { const now = new Date() const start = new Date(now.getFullYear(), now.getMonth() - 1, 1) const end = new Date(now.getFullYear(), now.getMonth(), 0) end.setHours(23, 59, 59, 999) startTime.value = parseTime(start) endTime.value = parseTime(end) } watch([() => startTime.value, () => endTime.value], ([newStart, newEnd]) => { const ranges = [ { num: 2, range: getTimeRange('本月') }, { num: 4, range: getTimeRange('今天') }, { num: 5, range: getTimeRange('昨天') }, { num: 6, range: getTimeRange('上月') }, ] const nowRange = [newStart, newEnd] const matched = ranges.find(i => JSON.stringify(i.range) === JSON.stringify(nowRange)) dateRangeType.value = matched ? matched.num : undefined emit('change') }) function getTimeRange(type) { const now = new Date() let start = new Date(), end = new Date() switch (type) { case '上月': start = new Date(now.getFullYear(), now.getMonth() - 1, 1) end = new Date(now.getFullYear(), now.getMonth(), 0) break case '本月': start = new Date(now.getFullYear(), now.getMonth(), 1) end = new Date(now.getFullYear(), now.getMonth() + 1, 0) break case '今天': start.setHours(0, 0, 0, 0) end.setHours(23, 59, 59, 999) break case '昨天': start.setDate(start.getDate() - 1) end.setDate(end.getDate() - 1) start.setHours(0, 0, 0, 0) end.setHours(23, 59, 59, 999) break } return [parseTime(start), parseTime(end)] } const { t } = i18n.global const dateList = [ { label: t('this_month'), value: 2 }, { label: t('today'), value: 4 }, { label: t('yesterday'), value: 5 }, { label: t('last_month'), value: 6 } ] </script>
<style scoped lang="scss">
.timeSeparationClassCenter { display: flex; align-items: center; background-color: #fff; box-shadow: inset 0 1px 0 0 var(--el-input-border-color), inset 0 -1px 0 0 var(--el-input-border-color); } .timeSeparationClassStart .el-input__wrapper { border-radius: var(--el-border-radius-base) 0 0 var(--el-border-radius-base); box-shadow: inset 1px 0 0 0 var(--el-input-border-color); } .timeSeparationClassEnd .el-input__wrapper { border-radius: 0; box-shadow: inset -1px 0 0 0 var(--el-input-border-color); } .timeSeparationClass_after .el-select__wrapper { border-radius: 0 var(--el-border-radius-base) var(--el-border-radius-base) 0; background-color: var(--el-fill-color-light); }
🚀 三、使用示例
<template> <TimeSeparation v-model:startTime="queryParams.startTime" v-model:endTime="queryParams.endTime" :default-time="2" @change="onDateChange" /> </template> <script setup> import TimeSeparation from '@/components/TimeSeparation.vue' const queryParams = reactive({ startTime: '', endTime: '' }) function onDateChange() { console.log('时间范围变化:', queryParams) } </script>
📚 四、Props & Emits API 文档
Props
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
startTime | string | '' | 外部绑定开始时间 |
endTime | string | '' | 外部绑定结束时间 |
defaultTime | number | 无 | 初始选中快捷选项(如 2:本月) |
showAfter | boolean | true | 是否显示快捷时间选择 |
Emits
事件名 | 参数 | 说明 |
---|---|---|
update:startTime | string | 绑定用 v-model:startTime |
update:endTime | string | 绑定用 v-model:endTime |
change | 无 | 时间范围变更回调 |
🧩 五、拓展建议(可选)
拓展方向 | 建议实现方法 |
---|---|
动态传入快捷项 | 增加 shortcuts: Array prop |
时间范围校验 | 内置日期合法性校验 + disabledDate |
表单集成支持 | 接入 <el-form-item> + rules |
可读性文本输出 | 增加 displayRange: computed 返回“xx 至 yy” |
到此这篇关于基于 Vue 3 + Element Plus自定义时间范围选择组件使用教程的文章就介绍到这了,更多相关vue elementplus时间范围选择组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!