vue时间组件DatePicker组件的手写示例

概述

在日常工作中,比不可少会用到时间组件,我们的第一反应就是直接到组件库去找一下现成的来用下,毕竟,时间组件看起来还是很复杂的,对于没接触过的人来说,要自己去写一个这样的组件出来,还是有难度的,但是作为一名前端开发,这么常见的组件,我们还是值得取自己写一个这样的组件的,现在就手把手带你实现vue中的DatePicker组件。看完不会找我。

前置知识

在开始写代码之前,建议代价先看看时间组件的布局,目前主流的组件库iview ,element等提供的时间组件布局都基本类似,功能也差不多,因此在这里实现的组件库的布局也也element家的布局差不多,大家先看下布局的最终样子。 这是日的时间组件,当我们这个能实现的时候,像那些年,月的就更简单了,因此这里我们只实现一个,其他的可以自己扩展。

vue时间组件DatePicker组件的手写示例_第1张图片

布局方面

  • 我们可以看到最终时间组件可以拆分为两大部分,最上面可以拆分为一个时间切换的组件,下面为一个table,用于记录日期,下面的表格我们又可以拆分为上面的星期组件,和下面的日期具体实现组件。
  • 然后,我们注意观察,表格是一个6行七列共计42个单元格的布局形式,包含上月的剩余天数,当前月份的全部天数,以及下月的开始天数,加起来组成42个单元格。其中上月和下月我们布局样式区别于当前月份的布局,还有就是当前天数的那个日期,我们需要高亮显示。

具体的实现思路

  • 在清楚布局之后,我们需要根据用户传入的时间,生成一个6*7=42的天数的td单元格,在这42个单元格中,包含上月剩余的天数,当前月份的全部天数,下月的开始天数。
  • 如果你清楚了步骤一,那么我们接下来就容易多了,我们要计算上月的天数,当前月份的全部天数,下月的开始天数,以及当前月份1号星期几。
  • 由于头部是星期日,星期一,星期二,星期三,星期四,星期五,星期六的布局,因此我们需要计算当前月份1号星期几,这样我们就能找到上月的剩余天数了,下月的剩余天数就等于42-当前月份天数-上月剩余天数。
  • 最后我们就需要提供计算月份天数,月份1号星期几,以及一个生成对应数据的工具函数了。

具体实现

目录结构

vue时间组件DatePicker组件的手写示例_第2张图片

utils.js(工具函数(核心))

  • .components/DatePicker/utils.js
/**
 * @Description  获取当前月份的天数
 * @param { Array } 年月组成的数组,例如:[2022,7]
 * @return {Number}例如:2022年7月有31天 返回31
 **/
export function getCurrentMonthCount([year, month]) {
  // 当我们实例化Date函数的时候,传入第三个参数为0可以通过getDate获取到当前月份具体有多少天
  return new Date(year, month, 0).getDate();
}
/**
 * @Description  获取当前月份1号是星期二几
 * @param { Array } 年月组成的数组,例如:[2022,7]
 * @return {Number}  例如2022-7-1是星期5,返回5
 **/
export function getFirstMonthDayWeek([year, month]) {
  return new Date(year, month - 1, 1).getDay();
}
/**
 * @Description  根据年月,组装渲染天的表格数据
 * @param { Array } 年月组成的数组,例如:[2022,7]
 * @return {Array}
 **/
/* 
在这里介绍下我们时间组件写法的思路:
1.对于时间组件的布局,可以先去参考iview element等开源组件库的date-picker组件的布局,基本上都是一样的
2.在清楚布局之后,我们需要根据用户传入的时间,生成一个6*7=42的天数的td单元格,在这42个单元格中,包含上月剩余的天数,当前月份的全部天数,下月的开始天数
3.如果你清楚了步骤二,那么我们接下来就容易多了,我们要计算上月的天数,当前月份的全部天数,下月的开始天数,以及当前月份1号星期几
4.由于头部是星期日,星期一,星期二,星期三,星期四,星期五,星期六的布局,因此我们需要计算当前月份1号星期几,这样我们就能找到上月的剩余天数了,下月的剩余天数就等于42-当前月份天数-上月剩余天数
5.在上面步骤知道后我们就可以着手根据上面提供的工具函数,生成我们需要的表格数据了
最终生成的是6*7的二维数组,因为表格天数的布局为6*7的布局,数据格式如下:
数组的个数代表了渲染的列数,内部每项数组代表每列的td个数
[
  [
    {
      //代表当前的td几号
       value: xxx,
       //上个月的号数和下个月的号数标识下,渲染的时候,我们样式另外布局
        disbled: true,
        //当前td的时间格式,用于点击了,给input显示以及供用户使用格式为2022-7-22
        date: xxx,
        // 当前天的时间td,我们需要高亮显示。添加标识
        active:xxx,
        //当前td的索引
        index: xxx,
    },
    {},
    {},
    {},
    {},
    {},
    {}
  ],
  [],
  [],
  [],
  [],
  [],
]
*/
export function genarateDayData([year, month]) {
  // 获取上月天数
  let lastMonthCount = getCurrentMonthCount([year, month - 1]);
  // 获取当月天数
  let currentMonthCount = getCurrentMonthCount([year, month]);
  // 获取当月1号星期
  let currentMonthFirstDayWeek = getFirstMonthDayWeek([year, month]);
  let dayList = [];
  let lastMonthPointer = 1;
  let currentMonthPoiner = 1;
  let nextMonthPointer = 1;
  // 根据日期组件的天数布局,共计42天,包含上月剩余天数+当月天数+下月初始天数
  for (let i = 0; i < 42; i++) {
    // 上个月需要渲染的td个数,以及对应的值
    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,
      });
    }
  }
  // 当前天数高亮
  // 最后将数据生成二维数组返回:对应的就是6*7的二维数组用于渲染天数表格列
  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(常量文件)
//用于保存组建的常量,静态数据,比如表头的星期
export const weekList = ["日", "一", "二", "三", "四", "五", "六"];

DatePicker.vue

  • .components/DatePicker/DatePicker.vue(整体包裹组件供外部使用)



DatePickerHead.vue

  • .components/DatePicker/DatePickerHead.vue(顶部时间切换组件)



DateTable.vue(表格组件)

  • .components/DatePicker/DateTable.vue



DatePickerWeekBar.vue(表头组件,渲染星期)

  • .components/DatePicker/DatePickerWeekBar.vue



DatePickerDayContent.vue

表格主题内容组件,用于渲染具体日期

  • .components/DatePicker/DatePickerDayContent.vue



index.js(按需导出文件)

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

使用

  • App.vue



最终效果

vue时间组件DatePicker组件的手写示例_第3张图片

总结

组件库很多看着很难的组件,只要我们认真斟酌,然后试着去是实现下,还是不难的,实现上面的这种类型的组件之后,其他的年和月类型的就更简答了,大家可以自己扩展,更多关于vue时间组件DatePicker组件的资料请关注脚本之家其它相关文章!

你可能感兴趣的:(vue时间组件DatePicker组件的手写示例)