這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
- npm包:sta-datepicker
- 效果圖

需求
普通的時間選擇器要么只能單選,要么只能選范圍,不可以隨意選擇若干個時間,同時大多數現成的時間選擇器選擇結束會收起來,很不方便,現在需求如下 1、可以自己控制展開收起 2、可以選擇不連續的多個時間范圍的日期 3、可以批量選中日期,不需要一個個點擊
實作程序(分幾個步驟,具體可以看原始碼)
1、生成一個日歷
-
頂部為固定的幾個按鈕,可以系結切換年份月份的函式
-
中間為固定的星期,一個七個
-
底部為具體日期,由三部分組成,即:上個月底幾天,這個月整個月,下個月初幾天
- 算好平年閏年,輸出當前月份第一天是周幾
- 根據當前月份的第一天的星期數,計算日歷要展示上個月月底的幾天
- 根據當前月份最后一天的星期數,計算日歷要展示下個月月初的幾天
-
日期部分使用div遍歷三個陣列,左浮動或者彈性盒直接堆起來即可
created() {
this.trueDateBox()
},
methods: {
trueDateBox() {
if (this.date === "") {
const date = new Date()
this.year = date.getFullYear()
this.updateLeapYear()
this.month = date.getMonth() + 1
this.day = null
}
this.dayScreen()
},
// 設定算好閏年平年
updateLeapYear() {
if (this.isLeapYear(this.year)) {
this.monthDay[1] = 29
} else {
this.monthDay[1] = 28
}
},
isLeapYear(year) {
return year % 100 === 0 ? year % 400 === 0 : year % 4 === 0
},
// 日期顯示
dayScreen() {
// 渲染上個月,第一行
const firstDate = new Date(this.year, this.month - 1, 1)
const firstWeek = firstDate.getDay()
let preMonthDay = null
if (this.month === 1) {
preMonthDay = this.monthDay[11]
} else {
preMonthDay = this.monthDay[this.month - 2]
}
console.log("preMonthDay", this.monthDay[11], this.month)
for (let i = 0; i < preMonthDay; i++) {
this.previousMonth[i] = i + 1
}
if (firstWeek === 0) {
this.previousMonth = this.previousMonth.slice(-7)
} else {
this.previousMonth = this.previousMonth.slice(-firstWeek)
console.log(33, this.previousMonth)
}
// 渲染下個月, 最后一行
const endDate = new Date(
this.year,
this.month - 1,
this.monthDay[this.month - 1]
)
const endWeek = endDate.getDay()
let nextMonthDay = null
if (this.month === 12) {
nextMonthDay = this.monthDay[0]
} else {
nextMonthDay = this.monthDay[this.month]
}
for (let i = 0; i < nextMonthDay; i++) {
this.nextMonth[i] = i + 1
}
if (endWeek === 6) {
this.nextMonth = this.nextMonth.slice(0, 7)
} else {
this.nextMonth = this.nextMonth.slice(0, 6 - endWeek)
}
},
}
2、系結四個固定的函式
- 點擊上一年,下一年,上個月,下個月時,需要計算跨年的情況
// 年份的增減
addYear() {
this.year++
this.updateLeapYear()
},
reduceYear() {
this.year--
this.updateLeapYear()
},
// 月份的增減
addMonth() {
this.month++
if (this.month > 12) {
this.month = 1
this.addYear()
}
},
reduceMonth() {
this.month--
if (this.month < 1) {
this.month = 12
this.reduceYear()
}
},
3、點擊具體日期時,確定狀態
- 使用陣列存起當前已選的日期,使用一個變數記錄當前半選的日期
- 通過一個函式
isActive給每個日期系結類名,從而在視圖上顯示出來,同時可以確定狀態的切換- 如果點擊了已選日期的資料,需要剔除,改為空白狀態
- 如果點擊了半選態日期,則直接選中當前日期,變為已選日期
- 如果點擊了空白狀態日期,則可能有兩種情況,一是已存在半選態日期,等待閉合,而是不存在半選態日期,當前設定為半選
methods: {
// 突出顯示當前日期
isActive(index) {
const date = new Date()
const y = date.getFullYear()
const m = date.getMonth() + 1
const d = date.getDate()
const obj = {}
if (this.year === y && this.month === m && index === d) {
obj.today = true
}
const newIndexStr = index < 10 ? `0${index}` : `${index}`
const newMonthStr = this.month < 10 ? `0${this.month}` : `${this.month}`
const item = `${this.year}/${newMonthStr}/${newIndexStr}`
if (item === this.partialSelect) {
obj.active = true
}
if (this.selctDate.includes(item)) {
obj.activeRange = true
}
return obj
},
selectDay(e, type) {
const iText = e.target.innerText
const sDate = Number(iText) < 10 ? `0${iText}` : `${iText}`
if (type === "previousMonth") {
if (this.month === 1) {
this.month = 12
this.reduceYear()
} else {
this.month = this.month - 1
}
} else if (type === "nextMonth") {
if (this.month === 12) {
this.month = 1
this.addYear()
} else {
this.month = this.month + 1
}
}
let arr = this.selctDate.map((i) => new Date(i).getTime())
const newMonthStr = this.month < 10 ? `0${this.month}` : `${this.month}`
const curSelectTime = `${this.year}/${newMonthStr}/${sDate}`
const curSelectTimeStamp = new Date(curSelectTime).getTime()
const clsName = e.target.className // 通過類名判斷當前是什么狀態
if (clsName.includes("activeRange")) {
// 點擊了范圍內的資料,需要剔除
arr = arr.filter((i) => i !== curSelectTimeStamp)
} else if (clsName.includes("active") && !clsName.includes("activeRange")) {
// 點擊了一個半選狀態的日期,準備擴展范圍或者單選一個
if (this.selctDate.length) {
const itemTime = arr[0]
const itemTime2 = arr[arr.length - 1]
const selectTime = curSelectTimeStamp
if (selectTime < itemTime) {
console.log("點擊了范圍之前的時間")
} else if (selectTime > itemTime2) {
console.log("點擊了范圍之后的時間")
} else {
console.log("點擊了范圍內的空白,直接加上一個")
}
arr = [...arr, curSelectTimeStamp]
console.log(arr)
} else {
// 第一次選擇日期,而且雙擊了,直接單獨確定這個
arr = [curSelectTimeStamp]
}
// 此時選擇完日前了,半選的日期消費掉了,清空
this.partialSelect = null
} else {
console.log("不是半選情況")
// 即沒有點擊范圍內,又不是半選狀態,可能是已經存在一個半選,等待這個日期來閉合范圍,也可能是第一次打開點擊
if (this.partialSelect) {
// 需要和已存在的半選態日期閉合
const itemTime = new Date(this.partialSelect).getTime()
const itemTime2 = curSelectTimeStamp
const timeArr = [itemTime, itemTime2].sort((a, b) => a - b) // 排序,因為不知道誰在前面
for (let i = timeArr[0]; i <= timeArr[1]; i += 86400000) {
arr.push(i)
}
// 此時確定好范圍了,半選的日期消費掉了,清空
this.partialSelect = null
} else if (this.selctDate.length) {
// 存在一個范圍,同時點擊范圍外,此時設定半選
this.day = sDate
this.partialSelect = curSelectTime
} else {
// 不存在一個范圍,所以是第一次點擊
this.day = sDate
this.partialSelect = curSelectTime
}
}
let filterArr = Array.from(new Set(arr))
filterArr = filterArr.sort((a, b) => a - b)
this.selctDate = filterArr.map((i) => this.formatTime(new Date(i)))
this.$emit("input", this.selctDate)
this.$emit("change", this.selctDate)
this.day = parseInt(sDate)
},
}
本文轉載于:
https://juejin.cn/post/7240088790423863353
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/555408.html
標籤:其他
下一篇:返回列表

