首頁  >  文章  >  web前端  >  使用Vue元件如何實現日曆(詳細教學)

使用Vue元件如何實現日曆(詳細教學)

亚连
亚连原創
2018-06-13 10:35:383698瀏覽

組件是我們學習vue必須會的一部分,以下這篇文章主要給大家介紹了關於Vue 組件(component)教程之實現精美的日曆的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或工作有一定的參考學習價值,需要的朋友們下面隨著我來一起學習學習吧。

元件(component)是Vue最強大的功能之一。元件可以擴充HTML元素,封裝可重複使用的程式碼,根據專案需求,抽象化一些元件,每個元件包含了展現、功能和樣式。每個頁面,根據自己的需要,使用不同的元件來拼接頁面。這種開發模式使得前端頁面易於擴展,且靈活性高,而且元件之間也實現了解耦。

最近應公司的要求,需要開發一個精美的日曆元件(IOS , 安卓, PC 的IE9 都能運作),寫完後想把它分享出來,希望大家批評。

先來個截圖

  

 程式碼已經分享到https://github.com/zhangKunUserGit/vue-component (本地下載)

使用方法

依需求先說怎麼用(上面是:HTML, 下面是JS )

<date-picker
 v-if="showDatePicker"
 :date="date"
 :min-date="minDate"
 :max-date="maxDate"
 @confirm="confirm"
 @cancel="cancel"
 ></date-picker>
import DataPicker from &#39;./components/DatePicker.vue&#39;;
import &#39;./style.scss&#39;;
new Vue({
 el: &#39;#app&#39;,
 data() {
 return {
 date: &#39;2017-09-11&#39;,
 minDate: &#39;2000-09-11&#39;,
 maxDate: &#39;2020-09-11&#39;,
 showDatePicker: false,
 selectedDate: &#39;点击选择日期&#39;,
 };
 },
 methods: {
 openDatePicker() {
 this.showDatePicker = true;
 },
 confirm(value) {
 this.showDatePicker = false;
 this.selectedDate = value;
 },
 cancel() {
 this.showDatePicker = false;
 },
 },
 components: {
 DataPicker,
 },
});

我們提供了最大值、最小值和初始值,唯一不足的地方是時間格式只能是YYYY-MM-DD (2017-12-12) ,大家可以從github上拉取程式碼運行看一下(由於沒有仔細測試,可能會有bug和效能問題,希望指出)。

(一)先畫好介面

這個不是重點,HTML 和CSS,應該很簡單,大家看我的css 可能感覺我的命名太長了,只因為我們公司用,擔心其他樣式影響它(可能有其他方式吧,希望大神指出)

##(二)組裝日期列表

先看程式碼:

rows() {
 const { year, month } = this.showDate;
 const months = (new Date(year, month, 0)).getDate();
 const result = [];
 let row = [];
 let weekValue;
 // 按照星期分组
 for (let i = 1; i <= months; i += 1) {
 // 根据日期获取星期,并让开头是1,而非0
 weekValue = (new Date(year, month, i)).getDay() + 1;
 // 判断月第一天在星期几,并填充前面的空白区域
 if (i === 1 && weekValue !== 1) {
 this.addRowEmptyValue(row, weekValue);
 this.addRowDayValue(row, i);
 } else {
 this.addRowDayValue(row, i);
 // 判断月最后一天在星期几,并填充后面的空白区域
 if (i === months && weekValue !== 7) {
 this.addRowEmptyValue(row, (7 - weekValue) + 1);
 }
 }
 // 按照一周分组
 if (weekValue % 7 === 0 || i === months) {
 result.push(row);
 row = [];
 }
 }
 this.showDate.monthStr = monthJson[this.showDate.month];
 return result;
},

我的想法是:

  (1)取得月份天數,並依照星期分組;

  (2)如果月份第一天不在星期一,前面填入空值。同理,如何月份最後一天不在周日,最後面填充空值,目的是:讓分的組 長度都是7,也就是一周。這樣可以用flex佈局方式快速開發了;

  (3)裡面也包含一些限制,例如小於minDate和大於maxDate, 不讓點擊等等

(三)切換月份

(1)上一月
/**
 * 切换到上一个月
 */
prevMonth() {
 if (this.prevMonthClick) {
 return;
 }
 this.prevMonthClick = true;
 setTimeout(() => {
 this.prevMonthClick = false;
 }, 500);
 this.fadeXType = &#39;fadeX_Prev&#39;;
 // 如何当前月份已经小于等于minMonth 就不让其在执行
 if (this.isMinLimitMonth()) {
 return;
 }
 const { year, month } = this.showDate;
 // 判断当前月份,如果已经等于1(1就是一月,而不是二月)
 if (month <= 1) {
 this.showDate.year = year - 1;
 this.showDate.month = 12;
 } else {
 this.showDate.month -= 1;
 }
},

setTimeout()主要是讓其顯示動畫後自動消失。 fadeXType 是動畫型別

(2)下一個月份
/**
 * 切换到下一个月
 */
nextMonth() {
 if (this.nextMonthClick) {
 return;
 }
 this.nextMonthClick = true;
 setTimeout(() => {
 this.nextMonthClick = false;
 }, 500);
 this.fadeXType = &#39;fadeX_Next&#39;;
 // 如何当前月份已经大于等于maxMonth 就不让其在执行
 if (this.isMaxLimitMonth()) {
 return;
 }
 const { year, month } = this.showDate;
 // 判断当前月份,如果已经等于12(12就是十二月)
 if (month >= 12) {
 this.showDate.year = year + 1;
 this.showDate.month = 1;
 } else {
 this.showDate.month += 1;
 }
},

這裡面的setTimeout() 和prevMonth方法的原理一樣。

上面兩種切換月份的功能主要注意:

   a. 因為有minDate和maxDate,所以首先考慮的是不能超出這個限制。

   b. 要考慮切換月份後年的變化,當月份大於12後,年加1 ,月變成 1。

(四)選擇年份

#(1)點選最上面的年,顯示年份清單#
openYearList() {
 if (this.showYear) {
 this.showYear = false;
 return;
 }
 const index = this.yearList.indexOf(this.selectDate.year);
 this.showYear = true;
 // 打开年列表,让其定位到选中的位置上
 setTimeout(() => {
 this.$refs.yearList.scrollTop = (index - 3) * 40;
 });
},

(2)選擇年份
selectYear(value) {
 this.showYear = false;
 this.showDate.year = value;
 let type;
 // 当日期在最小值之外,月份换成最小值月份 或者 当日期在最大值之外,月份换成最大值月份
 if (this.isMinLimitMonth()) {
 type = &#39;copyMinDate&#39;;
 } else if (this.isMaxLimitMonth()) { // 当日期在最大值之外,月份换成最大值月份
 type = &#39;copyMaxDate&#39;;
 }
 if (type) {
 this.showDate.month = this[type].month;
 this.showDate.day = this[type].day;
 this.resetSelectDate(this.showDate.day);
 return;
 }
 let dayValue = this.selectDate.day;
 // 判断日是最大值,防止另一个月没有这个日期
 if (this.selectDate.day > 28) {
 const months = (new Date(this.showDate.year, this.showDate.month, 0)).getDate();
 // 当前月份没有这么多天,就把当前月份最大值赋值给day
 dayValue = months < dayValue ? months : dayValue;
 }
 this.resetSelectDate(dayValue);
},

#在切換年份時注意一下方面:

    a.考慮minDate和maxDate,  因為如果之前你選擇的月份是1月,但是限制是9月,在大於minDate(比如2017) 年份沒有問題,但是到了minDate 的具體年份(比如2010),那麼月份最小值只能是九月,需要修改月份,maxDate同理。

 b. 如何之前你選擇的day是31,由於切換年份後,這個月只有30天,記得把day 換成這個月最大值,也就是30。

(五)處理原始資料

其實這一正常情況下,應該放在第一步講,但是我是根據我的開發習慣來寫步驟的。我通常都是先寫功能,數據是模擬的,等寫好了,再考慮原始數據格式和暴露具體的方法等等,因為這樣不會改來改去,影響開發和心情。

initDatePicker() {
 this.showDate = { ...this.splitDate(this.date, true) };
 this.copyMinDate = { ...this.splitDate(this.minDate) };
 this.copyMaxDate = { ...this.splitDate(this.maxDate) };
 this.selectDate = { ...this.showDate };
},
splitDate(date, addStr) {
 let result = {};
 const splitValue = date.split(&#39;-&#39;);
 try {
 if (!splitValue || splitValue.length < 3) {
 throw new Error(&#39;时间格式不正确&#39;);
 }
 result = {
 year: Number(splitValue[0]),
 month: Number(splitValue[1]),
 day: Number(splitValue[2]),
 };
 if (addStr) {
 result.week = (new Date(result.year, result.month, result.day)).getDay() + 1;
 result.monthStr = monthJson[result.month];
 result.weekStr = weekJson[result.week];
 }
 } catch (error) {
 console.error(error);
 }
 return result;
},

這裡目的是:

 a. 處理原始數據,把原始數據查分,用json快取下來,這樣方便後面操作和顯示。這裡面我只相容於YYYY-MM-DD的格式,其他的都不相容,如果你想相容其他格式,你可以修改其程式碼,或用moment.js 等其他函式庫幫你做這件事情。

 b. 拆分後的格式如下:

year: &#39;&#39;,
month: &#39;&#39;,
day: &#39;&#39;,
week: &#39;&#39;,
weekStr: &#39;&#39;,
monthStr: &#39;&#39;,

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

requireJS如何實作模組載入器?

js中實作MVVM框架(詳細教學)

#angularjs中有關scope作用域解釋

在javascript中如何實現高效能的載入順序

在axios中如何實現全域註冊

以上是使用Vue元件如何實現日曆(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn