基于 Vue 3 + Element Plus自定義時間范圍選擇組件使用教程
?? 自定義時間范圍選擇組件使用教程(基于 Vue 3 + Element Plus)
? 一個靈活實用的時間范圍選擇器,支持開始時間、結(jié)束時間、快捷時間選項、本地雙向綁定、插槽擴展等功能。


?? 一、功能介紹
該組件基于 Element Plus 的 <el-date-picker> 和 <el-select> 封裝,支持以下特性:
v-model:startTime和v-model:endTime雙向綁定;- 常用時間快捷選項:今天、昨天、本月、上月等;
- 自定義插槽
before,可拓展前置內(nèi)容; - 自動識別當前選擇是否為快捷項并高亮;
- 支持國際化
$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
| 參數(shù)名 | 類型 | 默認值 | 說明 |
|---|---|---|---|
startTime | string | '' | 外部綁定開始時間 |
endTime | string | '' | 外部綁定結(jié)束時間 |
defaultTime | number | 無 | 初始選中快捷選項(如 2:本月) |
showAfter | boolean | true | 是否顯示快捷時間選擇 |
Emits
| 事件名 | 參數(shù) | 說明 |
|---|---|---|
update:startTime | string | 綁定用 v-model:startTime |
update:endTime | string | 綁定用 v-model:endTime |
change | 無 | 時間范圍變更回調(diào) |
?? 五、拓展建議(可選)
| 拓展方向 | 建議實現(xiàn)方法 |
|---|---|
| 動態(tài)傳入快捷項 | 增加 shortcuts: Array prop |
| 時間范圍校驗 | 內(nèi)置日期合法性校驗 + disabledDate |
| 表單集成支持 | 接入 <el-form-item> + rules |
| 可讀性文本輸出 | 增加 displayRange: computed 返回“xx 至 yy” |
到此這篇關于基于 Vue 3 + Element Plus自定義時間范圍選擇組件使用教程的文章就介紹到這了,更多相關vue elementplus時間范圍選擇組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue 3.0 前瞻Vue Function API新特性體驗
這篇文章主要介紹了Vue 3.0 前瞻Vue Function API新特性體驗,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08
Vue-Cli配置代理轉(zhuǎn)發(fā)解決跨域問題的方法
本文主要介紹了Vue-Cli配置代理轉(zhuǎn)發(fā)解決跨域問題的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06
vue.extend,mixins和vue.component的區(qū)別及說明
Vue.extend 創(chuàng)建Vue的子類,可視為組件構(gòu)造函數(shù),Vue.mixin 允許全局添加方法或?qū)傩?方便所有組件使用,Vue.component 是插件注冊方法,通過Vue.extend創(chuàng)建的組件實例可以注冊到Vue全局,使其在任何組件中可用2024-09-09
Vue3組合式函數(shù)Composable實戰(zhàn)ref和unref使用
這篇文章主要為大家介紹了Vue3組合式函數(shù)Composable實戰(zhàn)ref和unref使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06

