el-date-picker日期范圍限制的實(shí)現(xiàn)
前言
最近遇到一個(gè)需求:需要限制報(bào)表下載的日期范圍,統(tǒng)一為半個(gè)月,防止用戶選擇范圍過(guò)廣,導(dǎo)致報(bào)表生成緩慢。
項(xiàng)目中使用的element-ui的el-date-picker日期選擇組件。
實(shí)現(xiàn)思路
- 1.由于頁(yè)面中有12處需要修改,所以需要對(duì)el-date-picker進(jìn)行二次封裝。
- 2.el-date-picker提供的picker-options中的disabledDate屬性可以對(duì)可選日期進(jìn)行動(dòng)態(tài)禁用與啟用。
- 3.disabledDate屬性只能針對(duì)選擇日期的情況,當(dāng)用戶手動(dòng)輸入日期時(shí),需要進(jìn)行攔截處理。
具體實(shí)現(xiàn)
聲明了全局組件HalfMonthPicker
組件模板定義
組件中使用v-bind="attrs"和v−on="attrs"和v-on="attrs"和v−on="listeners"進(jìn)行了屬性和事件透?jìng)?,方便后期維護(hù)。
<el-date-picker v-bind="$attrs" v-on="$listeners" :type="type" :range-separator="rangeSeparator" :start-placeholder="startPlaceholder" :end-placeholder="endPlaceholder" :value="value" :picker-options="pickerOptions"></el-date-picker>
定義props屬性 type
el-date-picker目前支持的范圍屬性為daterange和datetimerange,內(nèi)部使用了校驗(yàn)函數(shù),確保傳入的參數(shù)值,默認(rèn)為daterange。
props: { type: { type: String, default: 'daterange', validator(val) { return ['daterange', 'datetimerange'].includes(val) } } }
設(shè)置默認(rèn)屬性值
由于頁(yè)面中組件使用時(shí)都傳入了自定義的range-separator,start-placeholder,和end-placeholder,其屬性值相同,所以在組件內(nèi)部定義了props,并設(shè)置了默認(rèn)值,避免頁(yè)面中重復(fù)定義。
props: { rangeSeparator: { type: String, default: '至' }, startPlaceholder: { type: String, default: '起止日期' }, endPlaceholder: { type: String, default: '截止日期' } }
定義核心計(jì)算屬性pickerOptions
基本變量定義
currentFirstDate
首個(gè)選中的日期
currentFirstTime
首個(gè)選中的日期毫秒數(shù)
currentMinTime
小于currentFirstTime半個(gè)月的毫秒數(shù)
currentMaxTime
大于currentFirstTime半個(gè)月的毫秒數(shù)
currentTime
disabledDate函數(shù)傳入的日期值的毫秒數(shù),用于判斷是否在currentMinTime與currentMaxTime之間
shortcuts快捷選項(xiàng)
此處按照產(chǎn)品需求,內(nèi)置了最近一周和最近半個(gè)月的快捷選項(xiàng)。
disabledDate實(shí)現(xiàn)
如果存在currentFirstDate,將小于半月或超出半月的日期置為不可選中。
如果不存在,則皆可選。
onPick注意事項(xiàng)
1.當(dāng)maxDate和minDate都不存在
將currentFirstDate置為null,不限制日期選擇
2.minDate存在,而maxDate不存在
currentFirstDate = minDate,并限制日期選擇為前后半個(gè)月
3.maxDate和minDate同時(shí)存在
考慮如下情況,type為datetimerange時(shí),即使選中了開(kāi)始日期和結(jié)束日期,如果沒(méi)有點(diǎn)確定,彈框并不會(huì)消失,此時(shí)應(yīng)該可以重新選擇新的開(kāi)始日期,所以需要將currentFirstDate置為null,不在限制日期的選擇。
未置為null
置為null
computed: { pickerOptions() { const { value } = this // 選中的首個(gè)日期 let currentFirstDate = Array.isArray(value) && value.length === 1 && value[0] ? value[0] : null // 選中的首個(gè)日期毫秒數(shù) let currentFirstTime = null // 當(dāng)前日期毫秒數(shù) let currentTime = null // 當(dāng)前可選最小日期毫秒數(shù) let currentMinTime = null // 當(dāng)前可選最大日期毫秒數(shù) let currentMaxTime = null return { // 快捷選項(xiàng) shortcuts: [ { text: '最近一周', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 6) picker.$emit('pick', [start, end]) } }, { text: '最近半月', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 14) picker.$emit('pick', [start, end]) } } ], // 禁選邏輯 disabledDate(date) { if (currentFirstDate) { currentFirstTime = new Date(currentFirstDate).getTime() currentTime = new Date(date).getTime() currentMinTime = currentFirstTime - 3600 * 1000 * 24 * 15 currentMaxTime = currentFirstTime + 3600 * 1000 * 24 * 15 // 確保當(dāng)前可選日期在半月之間 return !(currentTime > currentMinTime && currentTime < currentMaxTime) } return false }, // 選中項(xiàng) onPick({ maxDate, minDate }) { // console.log(maxDate) currentFirstDate = !maxDate ? minDate : null } } } }
處理手動(dòng)輸入的情況
考慮如下場(chǎng)景,當(dāng)用戶選擇在input框中手動(dòng)輸入日期時(shí),pickerOptions中的disabledDate禁選屬性便無(wú)法對(duì)用戶產(chǎn)生攔截作用,此時(shí)便需要通過(guò)監(jiān)聽(tīng)value屬性的變化,當(dāng)newVal間隔大于半個(gè)月時(shí),重置回oldVal。
watch: { // 處理手動(dòng)輸入的情況 value: { handler(newVal, oldVal) { if (Array.isArray(newVal) && newVal.length === 2) { if (this.compareHalfMonthInterval(newVal[0], newVal[1])) { this.$message.warning('日期間隔不能超過(guò)半個(gè)月') // 重置為oldVal或null this.$emit('input', oldVal || null) } } }, immediate: true } }, methods: { /** * 比較時(shí)間是否超出半個(gè)月 * @param {*} startDate 開(kāi)始時(shí)間 * @param {*} endDate 結(jié)束時(shí)間 * @returns { boolean } true為超出半個(gè)月 */ compareHalfMonthInterval(startDate, endDate) { if (!startDate || !endDate) { return false } const startTime = new Date(startDate).getTime() const endTime = new Date(endDate).getTime() return (endTime - startTime) > 3600 * 1000 * 24 * 15 } }
頁(yè)面中使用
使用前
使用后
使用效果
選擇開(kāi)始日期
選擇結(jié)束日期
完整代碼實(shí)現(xiàn)
<template> <el-date-picker v-bind="$attrs" v-on="$listeners" :type="type" :range-separator="rangeSeparator" :start-placeholder="startPlaceholder" :end-placeholder="endPlaceholder" :value="value" :picker-options="pickerOptions"></el-date-picker> </template>
<script> export default { name: 'HalfMonthPicker', props: { type: { type: String, default: 'daterange', validator(val) { return ['daterange', 'datetimerange'].includes(val) } }, value: { type: Array, default: () => [] }, rangeSeparator: { type: String, default: '至' }, startPlaceholder: { type: String, default: '起止日期' }, endPlaceholder: { type: String, default: '截止日期' } }, computed: { pickerOptions() { const { value } = this // 選中的首個(gè)日期 let currentFirstDate = Array.isArray(value) && value.length === 1 && value[0] ? value[0] : null // 選中的首個(gè)日期毫秒數(shù) let currentFirstTime = null // 當(dāng)前日期毫秒數(shù) let currentTime = null // 當(dāng)前可選最小日期毫秒數(shù) let currentMinTime = null // 當(dāng)前可選最大日期毫秒數(shù) let currentMaxTime = null return { // 快捷選項(xiàng) shortcuts: [ { text: '最近一周', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 6) picker.$emit('pick', [start, end]) } }, { text: '最近半月', onClick(picker) { const end = new Date() const start = new Date() start.setTime(start.getTime() - 3600 * 1000 * 24 * 14) picker.$emit('pick', [start, end]) } } ], // 禁選邏輯 disabledDate(date) { if (currentFirstDate) { currentFirstTime = new Date(currentFirstDate).getTime() currentTime = new Date(date).getTime() currentMinTime = currentFirstTime - 3600 * 1000 * 24 * 15 currentMaxTime = currentFirstTime + 3600 * 1000 * 24 * 15 // 確保當(dāng)前可選日期在半月之間 return !(currentTime > currentMinTime && currentTime < currentMaxTime) } return false }, // 選中項(xiàng) onPick({ maxDate, minDate }) { // console.log(maxDate) currentFirstDate = !maxDate ? minDate : null } } } }, watch: { // 處理手動(dòng)輸入的情況 value: { handler(newVal, oldVal) { if (Array.isArray(newVal) && newVal.length === 2) { if (this.compareHalfMonthInterval(newVal[0], newVal[1])) { this.$message.warning('日期間隔不能超過(guò)半個(gè)月') // 重置為oldVal或null this.$emit('input', oldVal || null) } } }, immediate: true } }, methods: { /** * 比較時(shí)間是否超出半個(gè)月 * @param {*} startDate 開(kāi)始時(shí)間 * @param {*} endDate 結(jié)束時(shí)間 * @returns { boolean } true為超出半個(gè)月 */ compareHalfMonthInterval(startDate, endDate) { if (!startDate || !endDate) { return false } const startTime = new Date(startDate).getTime() const endTime = new Date(endDate).getTime() return (endTime - startTime) > 3600 * 1000 * 24 * 15 } } } </script>
到此這篇關(guān)于el-date-picker日期范圍限制的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)el-date-picker日期范圍限制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue條件循環(huán)判斷+計(jì)算屬性+綁定樣式v-bind的實(shí)例
今天小編就為大家分享一篇Vue條件循環(huán)判斷+計(jì)算屬性+綁定樣式v-bind的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Element中select多數(shù)據(jù)加載優(yōu)化的實(shí)現(xiàn)
本文主要介紹了Element中select多數(shù)據(jù)加載優(yōu)化的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09關(guān)于vue中ref的使用(this.$refs獲取為undefined)
這篇文章主要介紹了關(guān)于vue中ref的使用(this.$refs獲取為undefined),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Vue中iframe?結(jié)合?window.postMessage?實(shí)現(xiàn)跨域通信
window.postMessage()?方法可以安全地實(shí)現(xiàn)跨源通信,在一個(gè)項(xiàng)目的頁(yè)面中嵌入另一個(gè)項(xiàng)目的頁(yè)面,需要實(shí)現(xiàn)父子,子父頁(yè)面的通信,對(duì)Vue中iframe?結(jié)合?window.postMessage?實(shí)現(xiàn)跨域通信相關(guān)知識(shí)感興趣的朋友跟隨小編一起看看吧2022-12-12vue輸入框使用模糊搜索功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue輸入框使用模糊搜索功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05vue導(dǎo)出html、word和pdf的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue導(dǎo)出html、word和pdf的實(shí)現(xiàn)方法,文中完成了三種文件的導(dǎo)出但是還有很多種方法,小編就不給大家一一列舉了,需要的朋友可以參考下2018-07-07Vue.js實(shí)現(xiàn)一個(gè)todo-list的上移下移刪除功能
這篇文章主要介紹了Vue.js實(shí)現(xiàn)一個(gè)todo-list的上移下移刪除功能,需要的朋友可以參考下2017-06-06