vant實(shí)現(xiàn)自定義日期時(shí)間選擇器(年月日時(shí)分秒)
1 背景
使用vant作為UI組件時(shí),需要一個(gè)日期時(shí)間選擇器,vant中有Dateicker和TimePicker,可以將兩個(gè)組件組合封裝使用,但是處理傳入?yún)?shù)和傳出參數(shù)稍顯麻煩,所以使用Picker封裝一個(gè)簡(jiǎn)單的日期時(shí)間選擇器
2 要求
- 可以傳入初始值
- 可以選擇年,年月,年月日,年月日時(shí),年月日時(shí)分,年月日時(shí)分秒
- 可以限定選擇的最大日期和最小日期

3 實(shí)現(xiàn)
// DateTimePicker.vue
<template>
<van-picker
ref="picker"
title="請(qǐng)選擇時(shí)間"
:columns="columns"
@change="handleChange"
@cancel="handleCancel"
@confirm="handleConfirm"
v-model="values"
/>
</template>
<script setup lang="ts">
const props = defineProps({
// 顯示的列數(shù)量共6列(年月日時(shí)分秒)
columnCount: {
type: Number,
default: 6,
},
// 可以選擇的最小日期
minDate: {
type: Date,
default: new Date(new Date().getFullYear() - 10, 1, 1, 0, 0, 0),
},
// 可以選擇的最大日期
maxDate: {
type: Date,
default: new Date(new Date().getFullYear() + 10, 11, 31, 23, 59, 59),
},
});
const values = defineModel({
get(val) {
let param = val;
if (Array.isArray(param)) {
if (param.length > 0) {
return param.map(i => i.toString().padStart(2, '0'));
}
param = new Date();
} else if (!param) {
param = new Date();
}
const date = new Date(param);
const Y = date.getFullYear().toString();
const M = (date.getMonth() + 1).toString().padStart(2, '0'); //實(shí)際月份
const D = date.getDate().toString().padStart(2, '0');
const h = date.getHours().toString().padStart(2, '0');
const m = date.getMinutes().toString().padStart(2, '0');
const s = date.getSeconds().toString().padStart(2, '0');
return [Y, M, D, h, m, s];
},
});
const columns = ref([]); //所有時(shí)間列
const maxDateArray = computed(() => getDateArray(props.maxDate));
onBeforeMount(() => {
getColumns();
});
const getColumns = () => {
const options = [
{
radix: props.maxDate.getFullYear() - props.minDate.getFullYear() + 1,
base: props.minDate.getFullYear(),
},
{
radix: 12,
base: 1,
},
{
radix: getCountDays(values.value[0], values.value[1]),
base: 1,
},
{
radix: 24,
base: 0,
},
{
radix: 60,
base: 0,
},
{
radix: 60,
base: 0,
},
].slice(0, props.columnCount);
options.forEach((item, index) => {
columns.value.push(fillData(index, item.radix, item.base));
});
};
const fillData = (index, radix, baseNum = 0) => {
return Object.keys(new Array(radix).fill()).map(item => ({
text: (Number(item) + baseNum).toString().padStart(2, '0'),
value: (Number(item) + baseNum).toString().padStart(2, '0'),
disabled: Number(item) + baseNum > maxDateArray.value[index],
}));
};
const getCountDays = (year, month) => {
//獲取某年某月最后1天
return new Date(year, month, 0).getDate();
};
const getDateArray = param => {
const date = new Date(param);
const Y = date.getFullYear();
const M = date.getMonth() + 1; //實(shí)際月份
const D = date.getDate();
const h = date.getHours();
const m = date.getMinutes();
const s = date.getSeconds();
return [Y, M, D, h, m, s];
};
const handleChange = ({ selectedValues, columnIndex }) => {
const dateArray = [...selectedValues].map((i, idx) => {
if (idx == 1) {
return Number(i) - 1;
}
return Number(i);
});
const maxDate = maxDateArray.value.map((i, idx) => {
if (idx == 1) {
return Number(i) - 1;
}
return i;
});
if (columnIndex <= 1 && columns.value.length > 2) {
const lastDay = getCountDays(Number(selectedValues[0]), Number(selectedValues[1]));
columns.value[2] = fillData(2, lastDay, 1);
if (lastDay < Number(selectedValues[2])) {
//切換年列或者月列時(shí),因?yàn)槊吭碌奶炜赡懿煌?,所以天列需要重?
values.value = values.value
.map((item, idx) => {
if (idx === 2) {
return lastDay.toString();
}
return item;
})
.slice(0, props.columnCount);
}
}
if (
new Date(...dateArray.slice(0, columnIndex + 1)).getTime() <
new Date(...maxDate.slice(0, columnIndex + 1)).getTime()
) {
for (let i = columnIndex + 1; i < columns.value.length; i++) {
columns.value[i].forEach(k => {
k.disabled = false;
});
}
} else {
for (let i = columnIndex + 1; i < columns.value.length; i++) {
columns.value[i].forEach(k => {
if (Number(k.value) > maxDateArray.value[i]) {
k.disabled = true;
}
});
}
if (new Date(...dateArray).getTime() > new Date(...maxDate).getTime()) {
values.value = maxDateArray.value.slice(0, props.columnCount);
}
}
};
const handleCancel = () => {
emit('cancel');
};
const handleConfirm = ({ selectedValues }) => {
emit(
'confirm',
(selectedValues.slice(0, 3).join('-') + ' ' + selectedValues.slice(3).join(':')).trim()
);
};
const emit = defineEmits(['confirm', 'cancel']);
</script>
// index.vue
<template>
<van-button type="primary" @click="handleClick">選擇日期</van-button>
<van-popup v-model:show="showPicker" round position="bottom">
<DateTimePicker
v-model="values"
:maxDate="maxDate"
@cancel="handleCancel"
@confirm="handleConfirm"
/>
</van-popup>
</template>
<script setup lang="ts">
const maxDate = new Date();
const showPicker = ref(false);
const values = ref(['2025','12','23','12','01','12']);//設(shè)置初始日期時(shí)間
const handleConfirm = () => {
//點(diǎn)擊確定的事件
showPicker.value = false;
}
const handleCancel = () => {
//點(diǎn)擊取消的事件,比如關(guān)閉彈框
showPicker.value = false;
}
const handleClick = () => {
showPicker.value = true;
}
</script>
到此這篇關(guān)于vant實(shí)現(xiàn)自定義日期時(shí)間選擇器(年月日時(shí)分秒)的文章就介紹到這了,更多相關(guān)vant 日期時(shí)間選擇器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue使用vant實(shí)現(xiàn)日期選擇器功能
- 關(guān)于vant的時(shí)間選擇器使用方式
- vant4 封裝日期段選擇器的實(shí)現(xiàn)
- Vue配合Vant使用時(shí)area省市區(qū)選擇器的使用方式
- Vant picker選擇器設(shè)置默認(rèn)值導(dǎo)致選擇器失效的解決
- Vant?Weapp組件picker選擇器初始默認(rèn)選中問(wèn)題
- vant中的picker選擇器自定義選項(xiàng)內(nèi)容
- 基于Vant UI框架實(shí)現(xiàn)時(shí)間段選擇器
- Vue 用Vant實(shí)現(xiàn)時(shí)間選擇器的示例代碼
相關(guān)文章
Vue3結(jié)合TypeScript項(xiàng)目開發(fā)實(shí)踐總結(jié)
本文主要介紹了Vue3結(jié)合TypeScript項(xiàng)目開發(fā)實(shí)踐總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
vue+elementUI實(shí)現(xiàn)動(dòng)態(tài)面包屑
這篇文章主要為大家詳細(xì)介紹了vue+elementUI實(shí)現(xiàn)動(dòng)態(tài)面包屑,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
vite+vue3.0+ts+element-plus快速搭建項(xiàng)目的實(shí)現(xiàn)
本文將結(jié)合實(shí)例代碼,介紹vite+vue3.0+ts+element-plus快速搭建項(xiàng)目的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
vue-star評(píng)星組件開發(fā)實(shí)例
下面小編就為大家分享一篇vue-star評(píng)星組件開發(fā)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
離線搭建vue環(huán)境運(yùn)行項(xiàng)目完整步驟
這篇文章主要給大家介紹了關(guān)于離線搭建vue環(huán)境運(yùn)行項(xiàng)目的相關(guān)資料,文中通過(guò)實(shí)例代碼以及圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-06-06
詳解Vue內(nèi)部怎樣處理props選項(xiàng)的多種寫法
這篇文章主要介紹了詳解Vue內(nèi)部怎樣處理props選項(xiàng)的多種寫法,詳細(xì)的介紹了props的使用的寫法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
vue實(shí)例成員?插值表達(dá)式?過(guò)濾器基礎(chǔ)教程示例詳解
這篇文章主要為大家介紹了vue實(shí)例成員?插值表達(dá)式?過(guò)濾器基礎(chǔ)教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04

