亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

vue時間組件DatePicker組件的手寫示例

 更新時間:2022年07月27日 14:40:50   作者:陌年微涼_  
這篇文章主要為大家介紹了vue時間組件DatePicker組件的手寫實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

概述

在日常工作中,比不可少會用到時間組件,我們的第一反應就是直接到組件庫去找一下現(xiàn)成的來用下,畢竟,時間組件看起來還是很復雜的,對于沒接觸過的人來說,要自己去寫一個這樣的組件出來,還是有難度的,但是作為一名前端開發(fā),這么常見的組件,我們還是值得取自己寫一個這樣的組件的,現(xiàn)在就手把手帶你實現(xiàn)vue中的DatePicker組件??赐瓴粫椅?。

前置知識

在開始寫代碼之前,建議代價先看看時間組件的布局,目前主流的組件庫iview ,element等提供的時間組件布局都基本類似,功能也差不多,因此在這里實現(xiàn)的組件庫的布局也也element家的布局差不多,大家先看下布局的最終樣子。 這是日的時間組件,當我們這個能實現(xiàn)的時候,像那些年,月的就更簡單了,因此這里我們只實現(xiàn)一個,其他的可以自己擴展。

布局方面

  • 我們可以看到最終時間組件可以拆分為兩大部分,最上面可以拆分為一個時間切換的組件,下面為一個table,用于記錄日期,下面的表格我們又可以拆分為上面的星期組件,和下面的日期具體實現(xiàn)組件。
  • 然后,我們注意觀察,表格是一個6行七列共計42個單元格的布局形式,包含上月的剩余天數(shù),當前月份的全部天數(shù),以及下月的開始天數(shù),加起來組成42個單元格。其中上月和下月我們布局樣式區(qū)別于當前月份的布局,還有就是當前天數(shù)的那個日期,我們需要高亮顯示。

具體的實現(xiàn)思路

  • 在清楚布局之后,我們需要根據(jù)用戶傳入的時間,生成一個6*7=42的天數(shù)的td單元格,在這42個單元格中,包含上月剩余的天數(shù),當前月份的全部天數(shù),下月的開始天數(shù)。
  • 如果你清楚了步驟一,那么我們接下來就容易多了,我們要計算上月的天數(shù),當前月份的全部天數(shù),下月的開始天數(shù),以及當前月份1號星期幾。
  • 由于頭部是星期日,星期一,星期二,星期三,星期四,星期五,星期六的布局,因此我們需要計算當前月份1號星期幾,這樣我們就能找到上月的剩余天數(shù)了,下月的剩余天數(shù)就等于42-當前月份天數(shù)-上月剩余天數(shù)。
  • 最后我們就需要提供計算月份天數(shù),月份1號星期幾,以及一個生成對應數(shù)據(jù)的工具函數(shù)了。

具體實現(xiàn)

目錄結構

utils.js(工具函數(shù)(核心))

  • .components/DatePicker/utils.js
/**
 * @Description  獲取當前月份的天數(shù)
 * @param { Array } 年月組成的數(shù)組,例如:[2022,7]
 * @return {Number}例如:2022年7月有31天 返回31
 **/
export function getCurrentMonthCount([year, month]) {
  // 當我們實例化Date函數(shù)的時候,傳入第三個參數(shù)為0可以通過getDate獲取到當前月份具體有多少天
  return new Date(year, month, 0).getDate();
}
/**
 * @Description  獲取當前月份1號是星期二幾
 * @param { Array } 年月組成的數(shù)組,例如:[2022,7]
 * @return {Number}  例如2022-7-1是星期5,返回5
 **/
export function getFirstMonthDayWeek([year, month]) {
  return new Date(year, month - 1, 1).getDay();
}
/**
 * @Description  根據(jù)年月,組裝渲染天的表格數(shù)據(jù)
 * @param { Array } 年月組成的數(shù)組,例如:[2022,7]
 * @return {Array}
 **/
/* 
在這里介紹下我們時間組件寫法的思路:
1.對于時間組件的布局,可以先去參考iview element等開源組件庫的date-picker組件的布局,基本上都是一樣的
2.在清楚布局之后,我們需要根據(jù)用戶傳入的時間,生成一個6*7=42的天數(shù)的td單元格,在這42個單元格中,包含上月剩余的天數(shù),當前月份的全部天數(shù),下月的開始天數(shù)
3.如果你清楚了步驟二,那么我們接下來就容易多了,我們要計算上月的天數(shù),當前月份的全部天數(shù),下月的開始天數(shù),以及當前月份1號星期幾
4.由于頭部是星期日,星期一,星期二,星期三,星期四,星期五,星期六的布局,因此我們需要計算當前月份1號星期幾,這樣我們就能找到上月的剩余天數(shù)了,下月的剩余天數(shù)就等于42-當前月份天數(shù)-上月剩余天數(shù)
5.在上面步驟知道后我們就可以著手根據(jù)上面提供的工具函數(shù),生成我們需要的表格數(shù)據(jù)了
最終生成的是6*7的二維數(shù)組,因為表格天數(shù)的布局為6*7的布局,數(shù)據(jù)格式如下:
數(shù)組的個數(shù)代表了渲染的列數(shù),內(nèi)部每項數(shù)組代表每列的td個數(shù)
[
  [
    {
      //代表當前的td幾號
       value: xxx,
       //上個月的號數(shù)和下個月的號數(shù)標識下,渲染的時候,我們樣式另外布局
        disbled: true,
        //當前td的時間格式,用于點擊了,給input顯示以及供用戶使用格式為2022-7-22
        date: xxx,
        // 當前天的時間td,我們需要高亮顯示。添加標識
        active:xxx,
        //當前td的索引
        index: xxx,
    },
    {},
    {},
    {},
    {},
    {},
    {}
  ],
  [],
  [],
  [],
  [],
  [],
]
*/
export function genarateDayData([year, month]) {
  // 獲取上月天數(shù)
  let lastMonthCount = getCurrentMonthCount([year, month - 1]);
  // 獲取當月天數(shù)
  let currentMonthCount = getCurrentMonthCount([year, month]);
  // 獲取當月1號星期
  let currentMonthFirstDayWeek = getFirstMonthDayWeek([year, month]);
  let dayList = [];
  let lastMonthPointer = 1;
  let currentMonthPoiner = 1;
  let nextMonthPointer = 1;
  // 根據(jù)日期組件的天數(shù)布局,共計42天,包含上月剩余天數(shù)+當月天數(shù)+下月初始天數(shù)
  for (let i = 0; i < 42; i++) {
    // 上個月需要渲染的td個數(shù),以及對應的值
    if (lastMonthPointer <= currentMonthFirstDayWeek) {
      // 上月
      dayList.unshift({
        value: lastMonthCount--,
        disbled: true,
        date: year + "-" + (month - 1) + "-" + (lastMonthCount + 1),
        index: i,
      });
      lastMonthPointer++;
    } else if (currentMonthPoiner <= currentMonthCount) {
      // 當月
      dayList.push({
        value: currentMonthPoiner++,
        disbled: false,
        active:
          new Date().getFullYear() == year &&
          new Date().getMonth() + 1 == month &&
          currentMonthPoiner - 1 == new Date().getDate(),
        date: year + "-" + month + "-" + (currentMonthPoiner - 1),
        index: i,
      });
    } else {
      // 下月
      dayList.push({
        value: nextMonthPointer++,
        disbled: true,
        date: year + "-" + (month + 1) + "-" + (nextMonthPointer - 1),
        index: i,
      });
    }
  }
  // 當前天數(shù)高亮
  // 最后將數(shù)據(jù)生成二維數(shù)組返回:對應的就是6*7的二維數(shù)組用于渲染天數(shù)表格列
  let result = [];
  let index = 1;
  let i = 0;
  while (index <= 6) {
    let arr = [];
    for (let j = 0; j < 7; j++) {
      arr.push(dayList[i]);
      i++;
    }
    result.push(arr);
    index++;
  }
  return result;
}

constant.js

  • .components/DatePicker/constant.js(常量文件)
//用于保存組建的常量,靜態(tài)數(shù)據(jù),比如表頭的星期
export const weekList = ["日", "一", "二", "三", "四", "五", "六"];

DatePicker.vue

  • .components/DatePicker/DatePicker.vue(整體包裹組件供外部使用)
<template>
  <div class="date-picker-wrap">
    <div class="date-eidtor">
      <!-- 顯示時間的input -->
      <input
        type="text"
        :placeholder="placeholder"
        class="date-edit-input"
        v-model="currentDate"
        @click.stop="showDatePannel = !showDatePannel"
      />
    </div>
    <!-- 面包通過過渡組件包裹,實現(xiàn)顯示隱藏友好過渡 -->
    <transition name="date-picker">
      <div class="date-pocker-panel" v-show="showDatePannel">
        <!-- 時間控件的頭部,用戶切換年月 -->
        <date-picker-head
          @dateRangeChange="dateRangeChange"
          :date="curDate"
        ></date-picker-head>
        <!-- 主要的時間顯示列表組件,用于顯示對應月份的時間 -->
        <date-table :list="list" @dateChange="dateChange"></date-table>
      </div>
    </transition>
  </div>
</template>
<script>
import { genarateDayData } from "./utils";
import DatePickerHead from "./DatePickerHead.vue";
import DateTable from "./DateTable.vue";
export default {
  components: {
    DatePickerHead,
    DateTable,
  },
  props: {
    // 輸入框提示
    placeholder: {
      type: String,
      default: "選擇時間",
    },
    // 時間,為Date類型,默認為當前時間
    date: {
      type: Date,
      default() {
        return new Date();
      },
    },
  },
  data() {
    return {
      // 用于控制面包顯示與隱藏
      showDatePannel: false,
      // 表格數(shù)據(jù)
      list: [],
      // 處理props時間為數(shù)組格式[年,月]
      curDate: [this.date.getFullYear(), this.date.getMonth() + 1],
      // 用戶input顯示時間
      currentDate: "",
    };
  },
  mounted() {
    // 獲取當前月份的時間數(shù)據(jù)
    this.getDateList();
    // 除開時間組件的其他地方點擊,關閉時間面板
    window.addEventListener("click", () => {
      this.showDatePannel = false;
    });
  },
  methods: {
    // 監(jiān)聽每個td時間項點擊
    dateChange(date) {
      this.$emit("dateChange", date);
      this.showDatePannel = false;
      this.currentDate = date;
    },
    // 頭部年月切換
    dateRangeChange(type) {
      switch (type) {
        // 上一年點擊
        case "lastYear":
          this.curDate = [this.curDate[0] - 1, this.curDate[1]];
          break;
        // 上一月點擊(月份<1,就要返回到上一年的12月份)
        case "lastMonth":
          this.curDate = [
            this.curDate[1] - 1 <= 0 ? this.curDate[0] - 1 : this.curDate[0],
            this.curDate[1] - 1 <= 0 ? 12 : this.curDate[1] - 1,
          ];
          break;
        // 下一年點擊
        case "nextYear":
          this.curDate = [this.curDate[0] + 1, this.curDate[1]];
          break;
        case "nextMonth":
          // 下一月點擊(月份>12,就要到下一年的一月份)
          this.curDate = [
            this.curDate[1] + 1 > 12 ? this.curDate[0] + 1 : this.curDate[0],
            this.curDate[1] + 1 > 12 ? 1 : this.curDate[1] + 1,
          ];
          break;
      }
      this.getDateList();
    },
    // 通過props傳遞的時間,組裝成長度為42的數(shù)組,具體看utils文件下下面的這個方法
    getDateList() {
      this.list = genarateDayData(this.curDate);
    },
  },
};
</script>
<style lang="less">
.date-picker-wrap {
  position: relative;
  .date-pocker-panel {
    position: absolute;
    left: 0;
    top: 50px;
    width: 324px;
    height: 343px;
    color: #606266;
    border: 1px solid #e4e7ed;
    box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
    background: #fff;
    border-radius: 4px;
    line-height: 30px;
    padding: 12px;
    text-align: center;
  }
  .date-eidtor {
    width: 220px;
    .date-edit-input {
      background-color: #fff;
      background-image: none;
      border-radius: 4px;
      border: 1px solid #dcdfe6;
      box-sizing: border-box;
      color: #606266;
      display: inline-block;
      font-size: inherit;
      height: 40px;
      line-height: 40px;
      outline: none;
      padding: 0 15px;
      transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
      width: 100%;
    }
  }
  .date-picker-enter-active,
  .date-picker-leave-active {
    transition: all 0.25s ease;
  }
  .date-picker-enter,
  .date-picker-leave-to {
    opacity: 0;
    height: 0;
  }
}
</style>

DatePickerHead.vue

  • .components/DatePicker/DatePickerHead.vue(頂部時間切換組件)
<template>
  <!-- 頂部的時間切換組件 -->
  <div class="date-picker-head">
    <div class="arrow-left">
      <!-- 上一年點擊 -->
      <span class="last-year arrow" @click.stop="toogleDate('lastYear')"></span>
      <!-- 上一月點擊 -->
      <span class="last-month arrow" @click.stop="toogleDate('lastMonth')"></span>
    </div>
    <!-- 顯示當前的年和月 -->
    <div class="date-content">{{ date[0] + "年" + date[1] + "月" }}</div>
    <div class="arrow-right">
      <!-- 下一月點擊 -->
      <span class="next-month arrow" @click.stop="toogleDate('nextMonth')"></span>
      <!-- 下一年點擊 -->
      <span class="next-year arrow" @click.stop="toogleDate('nextYear')"></span>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    // 時間
    date: {
      type: Array,
      default() {
        return [new Date().getFullYear(), new Date().getMonth() + 1];
      },
    },
  },
  methods: {
    // 派發(fā)table事件處理邏輯,參數(shù)為當前td的時間,格式為2022-7-22
    toogleDate(type) {
      this.$emit("dateRangeChange", type);
    },
  },
};
</script>
<style lang="less">
.date-picker-head {
  display: flex;
  justify-content: space-between;
  margin-bottom: 12px;
  .last-year,
  .next-month {
    margin-right: 15px;
  }
  .arrow {
    cursor: pointer;
  }
}
</style>

DateTable.vue(表格組件)

  • .components/DatePicker/DateTable.vue
<template>
  <div class="date-table">
    <!-- 時間表格 -->
    <table>
      <!-- 頂部的星期組件 -->
      <date-picker-week-bar></date-picker-week-bar>
      <!-- 下方的6*7的月份天數(shù)組件 -->
      <date-picker-day-content
        :list="list"
        @dateChange="dateChange"
      ></date-picker-day-content>
    </table>
  </div>
</template>
<script>
import DatePickerWeekBar from "./DatePickerWeekBar.vue";
import DatePickerDayContent from "./DatePickerDayContent.vue";
export default {
  props: {
    // 表格數(shù)據(jù)
    list: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  components: {
    DatePickerWeekBar,
    DatePickerDayContent,
  },
  methods: {
    // 派發(fā)td天數(shù)點擊事件,參數(shù)為當前天數(shù)的時間格式為 2022-07-22
    dateChange(date) {
      this.$emit("dateChange", date);
    },
  },
};
</script>
<style lang="less">
.date-table {
  font-size: 12px;
}
</style>

DatePickerWeekBar.vue(表頭組件,渲染星期)

  • .components/DatePicker/DatePickerWeekBar.vue
<template>
  <thead class="date-picker-week-bar">
    <tr>
      <th v-for="item in weekList" :key="item">{{ item }}</th>
    </tr>
  </thead>
</template>
<script>
import { weekList } from "./constant.js";
export default {
  data() {
    return {
      weekList,
    };
  },
};
</script>
<style lang="less">
.date-picker-week-bar {
  th {
    width: 42px;
    height: 42px;
    color: #606266;
    font-weight: 400;
    border-bottom: 1px solid #ebeef5;
  }
}
</style>

DatePickerDayContent.vue

表格主題內(nèi)容組件,用于渲染具體日期

  • .components/DatePicker/DatePickerDayContent.vue
<template>
  <tbody class="date-picker-day-content">
    <tr v-for="(item, index) in list" :key="index">
      <td
        v-for="(subItem, index) in item"
        :key="index"
        :class="[
          subItem.disbled ? 'disble-item' : 'day-item',
          subItem.active ? 'active' : '',
          subItem.index == currentDay ? 'active-click' : '',
        ]"
        @click="handleDayClick(subItem)"
      >
        {{ subItem.value }}
      </td>
    </tr>
  </tbody>
</template>
<script>
export default {
  props: {
  //表格數(shù)據(jù)
    list: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  data() {
    return {
    //當前點擊項活躍高亮
      currentDay: -1,
    };
  },
  methods: {
    // 處理天的表格點擊,觸發(fā)關閉時間控件面板,設置時間input的值
    handleDayClick(item) {
      if (item.currentDay == item.index) return;
      this.currentDay = item.index;
      this.$emit("dateChange", item.date);
    },
  },
};
</script>
<style lang="less">
.date-picker-day-content {
  td {
    width: 40px;
    height: 40px;
    color: #606266;
    font-weight: 400;
    text-align: center;
    cursor: pointer;
  }
  .disble-item {
    cursor: not-allowed;
    color: #c0c4cc;
  }
  .day-item.active {
    color: #008c8c;
    font-weight: bold;
  }
  .day-item.active-click {
    border-radius: 50%;
    width: 30px;
    height: 30px;
    line-height: 30px;
    color: #fff;
    background-color: #008c8c;
  }
}
</style>

index.js(按需導出文件)

  • .components/DatePicker/index.js
import DatePicker from "./DatePicker.vue";
export { DatePicker };

使用

  • App.vue
<template>
  <div id="app">
    <div class="test-date-picker">
      <date-picker :date="date" @dateChange="dateChange"></date-picker>
    </div>
  </div>
</template>
<script>
import { DatePicker } from "./components/DatePicker/index";
export default {
  name: "App",
  components: {
    DatePicker,
  },
  data() {
    return {
      date: new Date(),
    };
  },
};
</script>
<style lang="less">
html,
body,
#app {
  height: 100%;
  width: 100%;
}
#app {
  .test-date-picker {
    width: 50%;
    margin: 20px auto;
  }
}
</style>

最終效果

總結

組件庫很多看著很難的組件,只要我們認真斟酌,然后試著去是實現(xiàn)下,還是不難的,實現(xiàn)上面的這種類型的組件之后,其他的年和月類型的就更簡答了,大家可以自己擴展,更多關于vue時間組件DatePicker組件的資料請關注腳本之家其它相關文章!

相關文章

  • vue 動態(tài)設置img的src地址無效,npm run build 后找不到文件的解決

    vue 動態(tài)設置img的src地址無效,npm run build 后找不到文件的解決

    這篇文章主要介紹了vue 動態(tài)設置img的src地址無效,npm run build 后找不到文件的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • VUE3傳值相關的6種方法總結

    VUE3傳值相關的6種方法總結

    件間傳參是vue開發(fā)過程中一個很常見的應用,對于我們后端開發(fā)來說,每次看到這種組件傳參的代碼就一頭霧水,下面這篇文章主要給大家介紹了關于VUE3傳值相關的6種方法,需要的朋友可以參考下
    2023-04-04
  • vue3 選中對話框時對話框右側出一個箭頭效果

    vue3 選中對話框時對話框右側出一個箭頭效果

    本文主要介紹了Vue3實現(xiàn)選中對話框帶箭頭效果的方法,首先通過后臺獲取數(shù)據(jù)進行遍歷,利用ts代碼判斷選中下標與循環(huán)游標是否一致以改變樣式,感興趣的朋友一起看看吧
    2024-10-10
  • vue-amap安裝和用法步驟

    vue-amap安裝和用法步驟

    vue-amap是餓了么開源的一套基于?Vue?2.0?和高德地圖的地圖組件。接下來通過本文給大家介紹vue-amap安裝和使用,需要的朋友可以參考下
    2021-12-12
  • 項目中如何使用axios過濾多次重復請求詳解

    項目中如何使用axios過濾多次重復請求詳解

    在項目開發(fā)中經(jīng)常需要處理重復點擊導致多次調(diào)用接口的問題,這篇文章主要介紹了項目中如何使用axios過濾多次重復請求的相關資料,需要的朋友可以參考下
    2021-07-07
  • Vue項目保存代碼之后頁面自動更新問題

    Vue項目保存代碼之后頁面自動更新問題

    這篇文章主要介紹了Vue項目保存代碼之后頁面自動更新問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • vue-quill-editor 自定義工具欄和自定義圖片上傳路徑操作

    vue-quill-editor 自定義工具欄和自定義圖片上傳路徑操作

    這篇文章主要介紹了vue-quill-editor 自定義工具欄和自定義圖片上傳路徑操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 1分鐘Vue實現(xiàn)右鍵菜單

    1分鐘Vue實現(xiàn)右鍵菜單

    今天給大家分享的是,如何在最短的時候內(nèi)實現(xiàn)右鍵菜單。高效實現(xiàn)需求,避免重復造輪子。感興趣的可以了解一下
    2021-10-10
  • vue項目webpack中配置src路徑別名及使用方式

    vue項目webpack中配置src路徑別名及使用方式

    這篇文章主要介紹了vue項目webpack中配置src路徑別名及使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue之debounce屬性被移除及處理詳解

    vue之debounce屬性被移除及處理詳解

    今天小編就為大家分享一篇vue之debounce屬性被移除及處理詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11

最新評論