前言
應用場景是公司的一個每日推薦專題需要加入日曆功能,點選日曆可以跳轉到當日的推薦。
設計圖:
關於日曆的實現
日曆實現的核心是利用js的Date物件(專案程式碼環境是依賴在vue當中)。
第一步:首頁展示
我們首先考慮我們日曆的第一頁,當前月。
要展示我們的當前月,首先我們需要三個資料:
- 當前年份
- 當前月份
- 月份下的日期列表
這些資料的初始化(注意這裡只是初始化,因為在日曆的使用過程中,他們是會隨著互動而變化的)狀態很好獲得,前兩個資料我們只需要通過:
this.curdate = new Date();
this.calendarMonth = this.curDate.getMonth() + 1; // 注意月份加1
this.calendarYear = this.curDate.getFullYear();
複製程式碼
值得一提的是我們的日期資料,因為這裡涉及到2個變數,第一個是每個月份的天數是不一樣的。第二個是每個月的1號是星期幾也是不固定的(而這個星期幾,則會影響到顯示上,1號應該從哪裡開始)。
直接貼上最終的獲取列表的程式碼:
/* 返回當月的日期表 */
getMonthList() {
// new Date()中的最後一個引數為0,表示的是當月的最後一天,
// 因此我們通過這一句獲得的就是傳入的年月的當月最後一天。
let date = new Date(this.calendarYear, this.calendarMonth, 0);
// 獲得當月的最後一天的日期號,就知道了當月有多少天
this.days = date.getDate();
// setDate(1)的作用是把日期變為當月的第一天
date.setDate(1);
// 在通過getDay(),就能知道當月的第一天是星期幾
let day = date.getDay();
// 獲得1號是星期幾後,在日曆上做一個偏移,這裡我採用的是補0
let delay = day - 1;
// 因為星期天在getDay的返回中是0,固特殊處理
if (day == 0) {
delay = 6;
}
let list = [];
for (let i = 0; i < this.days + delay; i++) {
if (i < delay) {
list.push(0);
} else {
list.push(i - delay + 1)
}
}
return list;
},
// 通過這個函式我們就獲得了當月的列表,格式類似於[0,0,0,1,2,3...31]
複製程式碼
第二步:響應變化
變化主要分為兩個方面:點選左右箭頭改變月份,點選具體的日期。
改變月份:
改變月份時我們要做的主要工作是改變我們用於記錄時間的變數(使用mvvm框架的好處是我們不需要關注檢視層面的改變,只需要專注我們的變數):
changeMonth(flag) {
// flag 記錄左右滑動,對應到月份就是加1和減1
this.curDate.setMonth(this.calendarMonth - 1 + flag);
// setNowDate() 函式裡面包括了我們每次改變日期時所需要做的工作,比如重新整理月份列表(即重新呼叫getMonthList函式等其他一些功能)
//如果我們要把日曆做成一個元件,那麼我們的函式中肯定需要觸發一個事件鉤子以反饋給外部例如:$emit(`monthChange`)
this.setNowDate();
},
複製程式碼
改變日期:
changeDay(day, el) {
// 改變我的當前顯示日期
this.curDate.setDate(day);
// clickedMonth是用來記錄我當前點選的月份,這個變數只隨點選改變,而不隨頁面翻動改變,主要是用來判斷當前日期的樣式用的。
this.clickedMonth = this.calendarMonth;
this.clickedYear = this.calendarYear;
// 獲取當前日曆的推薦資料(具體邏輯不贅述,這裡可以進行自己需要的操作)
this.getData(new Date(this.calendarYear, this.calendarMonth - 1, day), true)
this.setNowDate();
},
複製程式碼
點選了日期後,我們的樣式也會隨之改變:
// 計算樣式的函式
calDayCls(day) {
let cls = "calendar-li";
/* 檢視當前 */
if (day == this.calendarDay && this.calendarYear == this.clickedYear && this.calendarMonth == this.clickedMonth) {
cls += ` calendar-li-active`;
}
return cls
}
複製程式碼
至此,我們的日曆的核心功能就完成了,核心函式如下:
setNowDate // 改變控制當前日曆顯示的變數
changeMonth // 改變月份
getMonthList // 獲取月份日期表
changeDay // 改變日期
calDayCls // 計算當前日期的樣式
複製程式碼
有了這些核心部分,就基本實現了日曆的核心功能,然後就可以在上面新增更多的自定義的功能了,因為很多是涉及到我自己專案中個性化的東西,不具備過多參考價值,固沒有在程式碼體現。