真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

親自動手實現(xiàn)vue日歷控件

之前項目中有用到日歷控件,當時由于時間問題,是在網(wǎng)上找到一個demo,然后二次開發(fā)的,從那時就想著自己寫一個日歷控件。這篇文章說明日歷數(shù)據(jù)的處理,去除月份天數(shù)判斷以及是否閏年判斷。 

創(chuàng)新互聯(lián)主要從事成都做網(wǎng)站、成都網(wǎng)站制作、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務牟定,十多年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:18982081108

設計(以最常用的按月份的日歷)

日歷其實大家都很熟悉,一切的設計都是從功能出發(fā),這是根本。日歷的功能分為兩大塊。

  • 日歷頭部:當前年份/月份。
  • 日歷主體:當前月份的具體的日期信息。
  • 日歷主體的行數(shù):現(xiàn)在我們看到的日歷基本上為6行,因為一個月最多為31天,假設當前月的第一天為上一月最后一周的最后一天。如果是五行數(shù)據(jù)的話則只顯示了29天,這也是為什么顯示6行數(shù)據(jù)的原因。

功能點

  • 日歷初始渲染日期為當前月份
  • 頭部的左右滑動,日歷數(shù)據(jù)需要顯示對應月份的信息
  • 點擊日期本身可以進行相關數(shù)據(jù)操作,并且記錄操作內(nèi)容
  • 可以根據(jù)調(diào)用這設置日歷的每周數(shù)據(jù)以星期*為開始,星期天或者星期一。

首先思考日歷的核心問題

如何獲取當前日期的年份以及月份

/**
 * 獲取日歷header內(nèi)容 格式為:****年 **月
 * @param {*} date
 */
export const getHeaderContent = function (date) {
 let _date = new Date(date)
 
 return dateFormat(_date, 'yyyy年 MM月')
}

如何獲取當前月份需要顯示的42條數(shù)據(jù)(6*7),這42條數(shù)據(jù)是什么呢?

這個問題的核心是:當前月份顯示的42條數(shù)據(jù)的第一天是哪一天?

這個問題的解決思路還要從上面的設計說起,上面提到日歷主題的行數(shù)時,說到“假設當前月的第一天為上一月最后一周的最后一天”,那么42條數(shù)據(jù)顯示的內(nèi)容的第一條數(shù)據(jù)還要根據(jù)當前月的第一天是第一天所在周的第幾天。

舉例:2019-02-01

2月的第一天,星期五,所以當前月日歷的第一天為2019-02-01 - 5

var date = new Date()
date.setDate(date.getDate() - date.getDay() + 1) // 獲取當前月的第一天為2019-01-28

這里有一問題是什么呢?

date.getDate()的值為0 - 6(0為周日,如果你的日歷也是將周日放在日歷的第一天,沒什么問題,可是在中國是將周日放在最后一天的),這也就意味著前面的實現(xiàn)還需要考慮日歷的放置順序,因為日歷是按照普通的周一到周日,還是周日到周一,我們獲取的當月日歷的第一天是不同的。所以上面的代碼還要依賴于日歷的排放順序。

這里的排放順序?qū)⑹侨諝v組件的第一個可被調(diào)用者控制的參數(shù)。這里我的設想是將該參數(shù)的傳入值與date.getDay()匹配。

  • 0:周日
  • 1:周一
  • .....
  • 5:周五
  • 6:周六

所以上面的公式為

date.setDate(date.getDate() - date.getDay() + x)

但是這里的x值加了之后的日期如果大于當前月份的第一天,那就需要將當前得到的日期數(shù)值再減去7天,這個原因就不用說明了吧。

/**
 * 獲取當前月日歷的第一天
 * @param {*} date
 */
export const getFirstDayOfCalendar = function (date, weekLabelIndex) {
 let _date = new Date(date)
 _date = new Date(_date.setDate(_date.getDate() - _date.getDay() + weekLabelIndex))
 // 如果當前日期大于當前月第一天,則需要減去7天
 if (_date > date) {
 _date = new Date(_date.setDate(_date.getDate() - 7))
 }
 
 return _date
}

接下來就好做了,只需要在當前的日期加上加上1,每次得到下一天的日期。

左右切換月份如何設定

上面設計都是以今天為計算初始值,左右切換的初始值如何設計呢?

第一反應是將當前的日期的月份進行加減1,這樣是不行的,因為如果今天是31號,那么碰到下個月只有30的時候,這樣就會碰到點擊下月,直接切換了兩個月。更別說2月這個月份天數(shù)不固定的月份。所以這里又是一個問題了。

我的解決思路是:月份點擊切換的時候,初始計算值設計為當前月的第一天。

/**
 * 以傳入?yún)?shù)作為基準獲取下個月的第一天日期
 * @param {*} firstDayOfCurrentMonth
 */
export const getFirstDayOfNextMonth = function (firstDayOfCurrentMonth) {
 return new Date(firstDayOfCurrentMonth.getFullYear(), firstDayOfCurrentMonth.getMonth() + 1, 1)
}
 
/**
 * 以傳入?yún)?shù)作為基準獲取上個月的第一天日期
 * @param {*} firstDayOfCurrentMonth
 */
export const getFirstDayOfPrevMonth = function (firstDayOfCurrentMonth) {
 return new Date(firstDayOfCurrentMonth.getFullYear(), firstDayOfCurrentMonth.getMonth() - 1, 1)
}

左右切換月份數(shù)據(jù)傳遞方式(觀察者模式)

因為對于日歷組件本身來說,header和body是屬于同一個父組件的同級組件,數(shù)據(jù)傳遞可以依賴于父組件進行傳遞,這里我使用的是觀察者模式實現(xiàn)。

引入觀察者模式代碼:

/*
 * Subject
 * 內(nèi)部創(chuàng)建了三個方法,內(nèi)部維護了一個ObserverList。
 */
 
// contructor function
export const Subject = function () {
 this.observers = new ObserverList()
}
 
// addObserver: 調(diào)用內(nèi)部維護的ObserverList的add方法
Subject.prototype.addObserver = function (observer) {
 this.observers.add(observer)
}
 
// removeObserver: 調(diào)用內(nèi)部維護的ObserverList的removeat方法
Subject.prototype.removeObserver = function (observer) {
 this.observers.removeAt(this.observers.indexOf(observer, 0))
}
 
// notify: 通知函數(shù),用于通知觀察者并且執(zhí)行update函數(shù),update是一個實現(xiàn)接口的方法,是一個通知的觸發(fā)方法。
Subject.prototype.notify = function (context) {
 let observerCount = this.observers.count()
 for (let i = 0; i < observerCount; i++) {
 this.observers.get(i).update(context)
 }
}
 
/*
 * ObserverList
 * 內(nèi)部維護了一個數(shù)組,4個方法用于數(shù)組的操作,這里相關的內(nèi)容還是屬于subject,因為ObserverList的存在是為了將subject和內(nèi)部維護的observers分離開來,清晰明了的作用。
 */
function ObserverList () {
 this.observerList = []
}
 
ObserverList.prototype.add = function (obj) {
 return this.observerList.push(obj)
}
 
ObserverList.prototype.count = function () {
 return this.observerList.length
}
 
ObserverList.prototype.get = function (index) {
 if (index > -1 && index < this.observerList.length) {
 return this.observerList[index]
 }
}
 
ObserverList.prototype.indexOf = function (obj, startIndex) {
 let i = startIndex
 
 while (i < this.observerList.length) {
 if (this.observerList[i] === obj) {
  return i
 }
 i++
 }
 
 return -1
}
 
ObserverList.prototype.removeAt = function (index) {
 this.observerList.splice(index, 1)
}
 
/*
 * The Observer
 * 提供更新接口,為想要得到通知消息的主體提供接口。
 */
export const Observer = function () {
 this.update = function () {
 // ...
 }
}

CalendarBody觀察者注冊:

親自動手實現(xiàn)vue日歷控件

CalendarHeader通知消息

親自動手實現(xiàn)vue日歷控件

組件設計以及結構

VueCalendar
 
 Component
 
 CalendarBody.vue
 CalendarHeader.vue
 
 lib
 
 Subject.js 
 Util.js
 index.vue

當前效果

周一為第一天:

親自動手實現(xiàn)vue日歷控件

周日為第一天

親自動手實現(xiàn)vue日歷控件

Github地址

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。


當前名稱:親自動手實現(xiàn)vue日歷控件
網(wǎng)址分享:http://weahome.cn/article/ihjgcc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部