從0到1純手寫一個基於Vue的datepicker組件

在平常開發過程當中,咱們常常會有選擇日期和時間的需求,這時咱們須要datepicker組件來幫助咱們完成該需求。那麼datepicker組件是如何實現的呢,下面我來帶你們一塊兒實現一個基於Vue的datepicker組件吧。html

Date對象

在Javascript中,Date是關於操做日期和時間的對象,在實現datepicker的過程當中,咱們須要知道如何獲取一個月中的第一天和最後一天。git

let date = new Date(year,month,1)//獲取某年某月第一天
複製代碼

因爲Date對象具備越界退位的機制,因此獲取最後一天只須要獲取下個月的第0天便可。github

let date = new Date(year,month+1,0)//獲取某年某月最後一天
複製代碼

月份

由於每一年的月份都是固定不變的,這裏咱們只須要將月份數據寫爲常量而且經過一個函數輸出便可,而後在Vue組件中經過table標籤進行渲染。函數

getMonths(rows) {
    let result = [];
    let months = ['01','02','03','04','05','06','07','08','09','10','11','12'];
    let cols = Math.round(months.length / rows);
    for(let i=0;i<rows;i++) {
        result[i] = months.slice(i*cols,i*cols+cols);
    }
    return result;
}
複製代碼
<table>
    <tr v-for="(row,index) in months" :key="index">
        <td v-for="(m,i) in row" :key="i">
            <span class="fu-month-item" @click.stop="selectMonth(m)" :class="{'current':isCurrentMonth(m),'actived':isActivedMonth(m)}" >{{isCurrentMonth(m)?'當月':m}}</span>
        </td>
    </tr>
</table>
複製代碼

日期

爲了方便後期代碼維護,咱們將建立一個獲取某年某月所有日期的工具方法。工具

getYearMonthDates(year, month) {
    if (!year || !month) {
        let _date = new Date();
        year = _date.getFullYear();
        month = _date.getMonth() + 1;
    }
    let dates = [];
    //第一天
    let firstOfMonth = new Date(year, month - 1, 1);
    let firstDateDay = firstOfMonth.getDay();
    if (firstDateDay === 0) {
        //週日
        firstDateDay = 7
    }
    //最後一天
    let lastOfMonth = new Date(year, month, 0);
    let lastDateDay = lastOfMonth.getDay();
    if (lastDateDay === 0) {
        lastDateDay = 7;
    }
    let lastDateOfMonth = lastOfMonth.getDate();

    let prevMonthDayCount = firstDateDay - 1;
    let lastDateOfPrevMonth = new Date(year, month - 1, 0).getDate();

    for (let i = 0; i < 7 * 6; i++) {
        let enable = false;
        let _month = month;
        let date = i + 1 - prevMonthDayCount;
        let _showDate = date;
        if (date <= 0) {
            _month = month - 1;
            _showDate = lastDateOfPrevMonth + date;
        } else if (date > lastDateOfMonth) {
            _month = month + 1;
            _showDate = _showDate - lastDateOfMonth;
        } else {
            enable = true;
        }
        if (_month === 0) {
            _month = 12;
        }
        if (_month === 13) {
            _month = 1;
        }
        dates.push({
            year,
            month: _month,
            date: date,
            showDate: _showDate,
            enable
        })
    }
    return {
        year,
        month,
        days: dates
    }
}
複製代碼

有了這個方法,咱們就能夠獲取日期數據而且渲染界面了。ui

<div class="fu-datepicker-date" v-show="pickDate">
    <table>
        <thead>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
        </thead>
        <tbody>
            <tr v-for="(week,index) in days" :key="index">
                <td v-for="(day,index) in week" :key="index">
                    <span :class="{'gray':!day.enable,'actived':isActived(day),'today':isToday(day)}" class="fu-date-item" @click.stop="selectDate(day)" >{{isToday(day)?'今':day.showDate}}</span>
                </td>
            </tr>
        </tbody>
    </table>
</div>
複製代碼

時間

咱們經過下面三個方法獲取時間數據:spa

getHours() {
    let result = [];
    for (let i = 0; i < 24; i++) {
        let hour = `${i}`.padStart(2, '0');
        result.push(hour);
    }
    return result
},
getMinOrSec() {
    let result = [];
    for (let i = 0; i < 60; i++) {
        let hour = `${i}`.padStart(2, '0');
        result.push(hour);
    }
    return result
},
getMonths(rows) {
    let result = [];
    let months = ['01','02','03','04','05','06','07','08','09','10','11','12'];
    let cols = Math.round(months.length / rows);
    for(let i=0;i<rows;i++) {
        result[i] = months.slice(i*cols,i*cols+cols);
    }
    return result;
}
複製代碼

將獲取到的數據用列表渲染出來:code

<div class="time-picker-area">
    <div class="fu-time-item" v-for="(hour,index) in hours" :key="index" @click.stop="changeHour(hour)" :class="{'actived':isHourActived(hour)}" >{{hour}}</div>
</div>

<div class="time-picker-area">
    <div class="fu-time-item" v-for="(min,index) in minAndSecs" :key="index" @click.stop="changeMin(min)" :class="{'actived':isMinActived(min)}" >{{min}}</div>
</div>
<div class="time-picker-area">
    <div class="fu-time-item" v-for="(sec,index) in minAndSecs" :key="index" @click.stop="changeSec(sec)" :class="{'actived':isSecActived(sec)}" >{{sec}}</div>
</div>
複製代碼

這樣咱們就完成了一個最基本的datepicker組件。htm

Demo地址對象

總結

整體來講,實現datepicker組件的最關鍵思路在對於Javascript內置的Date對象的操做上面。在展現年、月份、日期、星期、時間等數據時,利用Date對象的越界退位機制獲取對應的數據,而後利於Vue將對應的數據渲染出來。

因爲篇幅有限,沒法將全部的代碼細節一一展示在這裏,若是有須要的童鞋能夠訪問GitHub項目倉庫fu-datepicker,有錯誤或者不明白的地方能夠留言,我會及時回覆你們,喜歡這個組件的能夠點個贊😊,共勉!

相關文章
相關標籤/搜索