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