日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

基于Vue开发一个日历组件

發(fā)布時間:2023/12/2 vue 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Vue开发一个日历组件 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最近在做一個類似課程表的需求,需要自制一個日歷來支持功能及展現(xiàn),就順便研究一下應該怎么開發(fā)日歷組件。

更新

  • 2.23修復了2026年2月份會渲染多一行的bug,謝謝@深藍一人童鞋提出的bug,解決方案是給二月份的日歷做特殊處理,new Date(year, month 1, 0).getDay() === 6時不會再渲染后面的日期。
  • 下班更新一哈,更科學的邏輯// if (total_calendar_list.length > 35) { // nextNum = 42 - total_calendar_list.length; // } else { // nextNum = 35 - total_calendar_list.length; // }// if (month === 1 && new Date(year, month, 0).getDay() === 6) { // nextNum = 0 // }nextNum = 6 - new Date(year, month 1, 0).getDay()

本文主要涉及以下內容:

  • 怎么開發(fā)一套日歷皮膚?
  • 怎么計算年月日?
  • 怎么開發(fā)日歷相關的功能?
  • 總結&DEMO源碼

怎么開發(fā)一套日歷皮膚?

層層分離,塊塊獨立

在梳理日歷邏輯之前我想先記錄一下日歷樣式相關的問題:

下面是借鑒px2rem模式,寫的基于vw為主單位的自適應轉化。簡單來說,就是在我們的設計稿是iPhone8一倍圖的情況下,計算出某元素寬度與375(iPhone8最大寬度)的比例再與100vw相乘就得到了,該元素的vw值。因為vw是相對于屏幕的百分比單位,所以就能達到我們想要的自適應效果啦,不同的屏幕里,同一元素的展現(xiàn)比例是一致的。

// 借鑒了Rem布局 @function pxWithVw($n) {@return 100vw * $n / 375; } // 規(guī)定極限寬度,避免PC上觀感太差 @function pxWithVwMax($n) {@return 480px * $n / 375; }

有了上面這段SCSS的函數(shù),我們就基本可以不用考慮屏幕適配的問題了,可以盡情的敲樣式啦。關于日歷的樣式,其實說復雜也還好,我們只需要在做之前好好的分一下層級就好了。

如同上圖,每一個框表示一層元素,最后會有這樣的布局--

<!--最外層的div限定整個日歷的寬度以及一些圓角陰影等樣式--> <div class="calendar"><!--header則為上圖中綠色框的內容,包含上下月切換以及日歷title--><div class="calendar__header"></div><!--顧名思義main則是整個日歷的核心內容,也就是日期的展示區(qū)域--><div class="calendar__main"><!--星期一~星期日的展示頭,列表渲染固定的7個block--><div class="main__block-head"></div><!--相應月份的日期展示區(qū)域,列表渲染--><div class="main__block"></div></div> </div>

也許大家看完之后比較奇怪calendar__main里面的布局,為什么沒有把固定的展示頭分離開來,當你實際寫到這里的時候會發(fā)現(xiàn)其實沒有這個必要。

因為我們用了pxWithVw去規(guī)定calendar__main的寬度以及每個block的寬度,也就確保了每7塊元素必定會占滿我們一行,再利用justify-content: space-around確保我們每塊元素的間隙一致即可。

好了,層層分離說完了,什么是塊塊獨立呢?

主要指的是日期的展示塊,我們是每塊獨立的,這樣在我們渲染的時候可以很方便的決定應該以什么樣式去展示他,或是應該給他綁定怎么樣的事件,給我們精密控制每個日期的展示提供了便利。

怎么計算年月日?

本小節(jié)的內容總結起來其實就一句話--

我們只需要知道,某個月的1號是星期幾,就能把整個日歷渲染出來

關于年月日的計算,我這邊有兩種模式,一種是只計算當月日期,另一種則是將整年的日期都計算出來。在本篇文章里我想著重記錄第一種寫法,大家想了解第二種的話可以到我的github里看看這個日歷的demo。

我們先來個看圖說話,這個二月份有28天,1號是星期四。那是不是說,我們只要從周四開始,按順序渲染出28個'main__block'就好了呢?其實就是這樣,關鍵是怎么把我們的1號定位到周四,只要這個能夠準確定位到,我們的日歷自然就出來了。

// 定義每個月的天數(shù),如果是閏年第二月改為29天 // year=2018;month=1(js--month=0~11) let daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {daysInMonth[1] = 29; } // 獲得指定年月的1號是星期幾 let targetDay = new Date(year, month, 1).getDay(); // 將要在calendar__main中渲染的列表 let total_calendar_list = []; let preNum = targetDay; // 首先先說一下,我們的日期是(日--六)這個順序也就是(0--6) // 有了上述的前提我們可以認為targetDay為多少,我們就只需要在total_calendar_list的數(shù)組中push幾個content為''的obj作為占位 if (targetDay > 0) {for (let i = 0; i < preNum; i ) {let obj = {type: "pre",content: ""};total_calendar_list.push(obj);} }

這樣一來,1號的位置自然而然就到了我們需要的星期四了,接下來就只需要按順序渲染就ok啦。下面是剩下日期數(shù)組填充,填充完畢之后return出來供我們view層使用。

for (let i = 0; i < daysInMonth[month]; i ) {let obj = {type: "normal",content: i 1};total_calendar_list.push(obj); } nextNum = 6 - new Date(year, month 1, 0).getDay() // 與上面的type=pre同理 for (let i = 0; i < nextNum; i ) {let obj = {type: "next",content: ""};total_calendar_list.push(obj); } return total_calendar_list;

怎么開發(fā)日歷相關的功能?

如何選擇上一個月或下一個月?

data() {return {// ...selectedYear: new Date().getFullYear(),selectedMonth: new Date().getMonth(),selectedDate: new Date().getDate()}; }handlePreMonth() {if (this.selectedMonth === 0) {this.selectedYear = this.selectedYear - 1this.selectedMonth = 11this.selectedDate = 1} else {this.selectedMonth = this.selectedMonth - 1this.selectedDate = 1} }handleNextMonth() {if (this.selectedMonth === 11) {this.selectedYear = this.selectedYear 1this.selectedMonth = 0this.selectedDate = 1} else {this.selectedMonth = this.selectedMonth 1this.selectedDate = 1} }

就是這么簡單,需要注意的點是跨年的時間轉換,我們需要在變更月份的同時把年份也改變,這樣才能渲染出正確的日期。

也許大家會有疑問,怎么變更了月份或年份之后不需要重新計算一次日期呢?其實是有計算的,不知大家是否還記得,vue可是數(shù)據驅動變更的,我們只需要關注數(shù)據的變更即可,其他東西vue都會幫我們解決。

如果選中某一天?

handleDayClick(item) {if (item.type === 'normal') {// do anything...this.selectedDate = Number(item.content)} }

在渲染列表的時候我就給每一個block綁定了click事件,這樣做的好處就是調用十分方便,點擊每一個block的時候,可以獲取該block的內容然后do anything you like

當然我們也可以給外層的父級元素綁定事件監(jiān)聽,通過事件流來解決每個block的點擊事件,這里看個人習慣~畢竟元素數(shù)量不是特別多

總結

一個移動端日歷貌似也有驚無險的完成啦,總體來說日歷這活還是偏樣式方面的,對邏輯的要求不是特別高,對樣式的要求倒是挺高的需要對flexbox布局有一定理解,才能迅速的吧日歷的骨架搭起來,雖然也不一定說必須用flex,不過個人認為用flex的效率會稍高一些。

基于Vue寫的日歷DEMO--Github

啰嗦一下,為什么想起來寫日歷?當然是業(yè)務需求啦,所以說這個日歷組件一開始是react寫的,后面想在vue里也嘗試一下就改成了vue。其實在react里面寫也是大同小異啦,只不過我會把日期的block抽離成無狀態(tài)組件,也不為啥就感覺比較好看:)

總結

以上是生活随笔為你收集整理的基于Vue开发一个日历组件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。