使用Vue元件如何實現日曆(詳細教學)
組件是我們學習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 './components/DatePicker.vue'; import './style.scss'; new Vue({ el: '#app', data() { return { date: '2017-09-11', minDate: '2000-09-11', maxDate: '2020-09-11', showDatePicker: false, selectedDate: '点击选择日期', }; }, 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 = 'fadeX_Prev';
// 如何当前月份已经小于等于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 是動畫型別/** * 切换到上一个月 */ prevMonth() { if (this.prevMonthClick) { return; } this.prevMonthClick = true; setTimeout(() => { this.prevMonthClick = false; }, 500); this.fadeXType = 'fadeX_Prev'; // 如何当前月份已经小于等于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; } },
(2)下一個月份/**
* 切换到下一个月
*/
nextMonth() {
if (this.nextMonthClick) {
return;
}
this.nextMonthClick = true;
setTimeout(() => {
this.nextMonthClick = false;
}, 500);
this.fadeXType = 'fadeX_Next';
// 如何当前月份已经大于等于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方法的原理一樣。 /** * 切换到下一个月 */ nextMonth() { if (this.nextMonthClick) { return; } this.nextMonthClick = true; setTimeout(() => { this.nextMonthClick = false; }, 500); this.fadeXType = 'fadeX_Next'; // 如何当前月份已经大于等于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; } },
上面兩種切換月份的功能主要注意:
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;
});
},
登入後複製
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 = 'copyMinDate';
} else if (this.isMaxLimitMonth()) { // 当日期在最大值之外,月份换成最大值月份
type = 'copyMaxDate';
}
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);
},
登入後複製
selectYear(value) { this.showYear = false; this.showDate.year = value; let type; // 当日期在最小值之外,月份换成最小值月份 或者 当日期在最大值之外,月份换成最大值月份 if (this.isMinLimitMonth()) { type = 'copyMinDate'; } else if (this.isMaxLimitMonth()) { // 当日期在最大值之外,月份换成最大值月份 type = 'copyMaxDate'; } 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('-'); try { if (!splitValue || splitValue.length < 3) { throw new Error('时间格式不正确'); } 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: '', month: '', day: '', week: '', weekStr: '', monthStr: '',
以上是使用Vue元件如何實現日曆(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在 Vue.js 中使用 Bootstrap 分為五個步驟:安裝 Bootstrap。在 main.js 中導入 Bootstrap。直接在模板中使用 Bootstrap 組件。可選:自定義樣式。可選:使用插件。

可以通過以下步驟為 Vue 按鈕添加函數:將 HTML 模板中的按鈕綁定到一個方法。在 Vue 實例中定義該方法並編寫函數邏輯。

Vue.js 中的 watch 選項允許開發者監聽特定數據的變化。當數據發生變化時,watch 會觸發一個回調函數,用於執行更新視圖或其他任務。其配置選項包括 immediate,用於指定是否立即執行回調,以及 deep,用於指定是否遞歸監聽對像或數組的更改。

Vue 多頁面開發是一種使用 Vue.js 框架構建應用程序的方法,其中應用程序被劃分為獨立的頁面:代碼維護性:將應用程序拆分為多個頁面可以使代碼更易於管理和維護。模塊化:每個頁面都可以作為獨立的模塊,便於重用和替換。路由簡單:頁面之間的導航可以通過簡單的路由配置來管理。 SEO 優化:每個頁面都有自己的 URL,這有助於搜索引擎優化。

在 Vue.js 中引用 JS 文件的方法有三種:直接使用 <script> 標籤指定路徑;利用 mounted() 生命週期鉤子動態導入;通過 Vuex 狀態管理庫進行導入。

Vue.js 返回上一頁有四種方法:$router.go(-1)$router.back()使用 <router-link to="/"> 組件window.history.back(),方法選擇取決於場景。

Vue.js 遍歷數組和對像有三種常見方法:v-for 指令用於遍歷每個元素並渲染模板;v-bind 指令可與 v-for 一起使用,為每個元素動態設置屬性值;.map 方法可將數組元素轉換為新數組。

Vue 中 div 元素跳轉的方法有兩種:使用 Vue Router,添加 router-link 組件。添加 @click 事件監聽器,調用 this.$router.push() 方法跳轉。
