博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
前端项目框架搭建随笔---DatePicker组件编写
阅读量:6876 次
发布时间:2019-06-26

本文共 19524 字,大约阅读时间需要 65 分钟。

距离上次更新13天了。。。

时间过的可真快

好的,让我们切入正题:

今天我们来做一个DatePicker(时间选择器)

如图:

由于时间紧迫,只实现了传入开始时间和结束时间的功能

使用插件:,

我们先上HTML和CSS代码

HTML+CSS

复制代码

复制代码

data/props里的变量:

props: {  startTime: { // 开始时间    required: false  },  endTime: { // 结束时间    required: false  }},data() {  return {    scrollParam: { //scroll通用参数      scrollY: true,      bounce: true,      wheel: {        selectedIndex: 0,        rotate: 25,        wheelWrapperClass: 'wheel-scroll',        wheelItemClass: 'wheel-item'      }    },    dateItem: {      yearsItem: [], //年份列表      monthsItem: [], //月份列表      daysItem: [], //天数列表      hoursItem: [], //时列表      minsItem: [] //分列表    },    selectItem: {      year: { //当前选择的年份        value: 0,        index: 0      },      month: { //当前选择的月份        value: 0,        index: 0      },      day: { //当前选择的天        value: 0,        index: 0      },      hour: { //当前选择的时        value: 0,        index: 0      },      min: { //当前选中的分        value: 0,        index: 0      },    }  }},复制代码

还有两个import

import BScroll from 'better-scroll'import dateUtils from '@/utils/tools/DateUtils'复制代码复制代码

实现思路

首先我们先列出开发中的预知问题:

  1. 天数多月份向天数少月份转换问题
  2. 开始时间和结束时间日期圈定
  3. 更改年份后同步更改子时间单位

看起来很容易解决,但串联起来不容易

思考了半天,想了这么一种解决思路:

仔细阅读的小伙伴可能就了解了,我这种解决思路是层层递减的。也就是选中我所选择的单位时,只刷新他的子单位列表,不刷新父单位列表。

上代码:

对此我们二次封装了一堆获取日期列表的方法,供大家参考:

getYearsItems(startDate, endDate) { //获取年列表  return dateUtils.getYearItems({    format: '{value}年',    startDate: startDate ? startDate : '',    endDate: endDate ? endDate : ''  })},getMonthItems(currentYear, startDate, endDate) { //获取月列表  return dateUtils.getMonthItems({    format: '{value}月',    startDate: startDate ? startDate : '',    endDate: endDate ? endDate : '',    currentYear: currentYear ? currentYear : ''  })},getDaysItems(currentYear, currentMonth, startDate, endDate) { //获取天列表  return dateUtils.getDayItems({    format: '{value}日',    startDate: startDate ? startDate : '',    endDate: endDate ? endDate : '',    currentYear: currentYear ? currentYear : '',    currentMonth: currentMonth ? currentMonth : '',  })},getHoursItems(currentYear, currentMonth, currentDay, startHour, endHour, startDate, endDate) {  return dateUtils.getHourItems({ //获取时列表    format: '{value}时',    startDate: startDate ? startDate : '',    endDate: endDate ? endDate : '',    currentYear: currentYear ? currentYear : '',    currentMonth: currentMonth ? currentMonth : '',    currentDay: currentDay ? currentDay : '',    startHour: startHour ? startHour : 0,    endHour: endHour ? endHour : 23  })},getMinsItems(currentYear, currentMonth, currentDay, currentHour, startDate, endDate) {  return dateUtils.getMinuteItems({ //获取分列表    format: '{value}分',    startDate: startDate ? startDate : '',    endDate: endDate ? endDate : '',    currentYear: currentYear ? currentYear : '',    currentMonth: currentMonth ? currentMonth : '',    currentDay: currentDay ? currentDay : '',    currentHour: currentHour ? currentHour : '',  })},复制代码复制代码

获取时列表那里还需要传入开始时和结束时。空的话默认0时 - 23时

初始化:

mounted() {  if (this.startTime && this.endTime) { //如果含有开始和结束时间    this.dateItem.yearsItem = this.getYearsItems(this.startTime, this.endTime); //按照开始结束时间获取年份列表    this.dateItem.monthsItem = this.getMonthItems(new Date(this.startTime).getFullYear(),      this.startTime, this.endTime); //同上    this.dateItem.daysItem = this.getDaysItems(new Date(this.startTime).getFullYear(),      new Date(this.startTime).getMonth() + 1,      this.startTime, this.endTime);  //同上    this.dateItem.hoursItem = this.getHoursItems(new Date(this.startTime).getFullYear(),      new Date(this.startTime).getMonth() + 1,      new Date(this.startTime).getDate(),      new Date(this.startTime).getHours(), 23,      this.startTime, this.endTime);  //同上    this.dateItem.minsItem = this.getMinsItems(new Date(this.startTime).getFullYear(),      new Date(this.startTime).getMonth() + 1,      new Date(this.startTime).getDate(),      new Date(this.startTime).getHours(),      this.startTime, this.endTime)  //同上  } else { //如果不存在开始结束时间    this.dateItem.yearsItem = this.getYearsItems(); //默认为空 获取当前日期前后100年的时间    this.dateItem.monthsItem = this.getMonthItems(); //默认为空 获取当前日期前后100年的时间    this.dateItem.daysItem = this.getDaysItems(); //默认为空 获取当前日期前后100年的时间    this.dateItem.hoursItem = this.getHoursItems();  //默认为空 获取当前日期前后100年的时间    this.dateItem.minsItem = this.getMinsItems(); //默认为空 获取当前日期前后100年的时间  }  this.$nextTick(() => { //data更新后    //初始化当前选择项    this.selectItem.year.value = this.dateItem.yearsItem[0].value; //获取时间列表第一个的value给默认值    this.selectItem.year.index = 0;  //初始化日期选择列表的index为0    this.selectItem.month.value = this.dateItem.monthsItem[0].value;    this.selectItem.month.index = 0;    this.selectItem.day.value = this.dateItem.daysItem[0].value;    this.selectItem.day.index = 0;    this.selectItem.hour.value = this.dateItem.hoursItem[0].value;    this.selectItem.hour.index = 0;    this.selectItem.min.value = this.dateItem.minsItem[0].value;    this.selectItem.min.index = 0;    this.initScroll();  //初始化scroll  });},复制代码

注释已经写的很清楚了~~~~

接下来我们以年列表滚动监听事件为注释例子,方便大家理解(initScroll方法):

let self = this; //新建变量重新指向this//年列表滚动let YearsScroll = new BScroll(document.getElementsByClassName("datetime--years")[0], this.scrollParam); //初始化scrollYearsScroll.on('scrollEnd', () => { //scrollEnd监听事件  let selectYear = self.dateItem.yearsItem[YearsScroll.getSelectedIndex()].value; //获取当前选中的年份  let selectMonth = self.dateItem.monthsItem[MonthsScroll.getSelectedIndex()].value; //获取当前选中的月份  let selectDay = self.selectItem.day.value;  //获取当前选中的天  self.selectItem.year.value = selectYear; //更新选中的年份  self.selectItem.year.index = YearsScroll.getSelectedIndex();  //更新选中的年份  if (self.startTime && self.endTime) {  //如果有开始结束日期    if (new Date(self.startTime).getFullYear() === selectYear) { //如果开始年份===当前选择年份      self.$nextTick(() => {        // 重新刷新月份列表 传入开始日期的年份,开始的时间和结束时间        self.dateItem.monthsItem = self.getMonthItems(new Date(self.startTime).getFullYear(), self.startTime, self.endTime);        // 更新当前选中月份        self.fixMonthDateBug();      });      self.$nextTick(() => {        // 重新刷新天份列表 传入开始日期的年份,开始时间的月份,开始的时间和结束时间        self.dateItem.daysItem = self.getDaysItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          self.startTime, self.endTime);        // 更新当前选中天        self.fixDaysDateBug();      });      self.$nextTick(() => {        // 重新刷新时列表 传入开始日期的年份,开始时间的月份,开始时间的天份,开始时刻-23时。        self.dateItem.hoursItem = self.getHoursItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          new Date(self.startTime).getDate(),          new Date(self.startTime).getHours(), 23);        // 更新当前选中时        self.fixHourDateBug();      });      self.$nextTick(() => {        // 重新刷新分列表 传入开始日期的年份,开始时间的月份,开始时间的天份,开始时刻,开始的时间和结束时间        self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          new Date(self.startTime).getDate(),          new Date(self.startTime).getHours(), self.startTime, self.endTime);        // 更新当前选中分        self.fixMinDateBug();      });      return false;    } else if (new Date(self.endTime).getFullYear() === selectYear) { //如果是结束时间 与开始时间同理      // 您选中了最后一个年份      self.dateItem.monthsItem = self.getMonthItems(        new Date(self.endTime).getFullYear(),        self.startTime, self.endTime);      self.$nextTick(() => {        self.fixMonthDateBug();      });      self.$nextTick(() => {        self.dateItem.daysItem = self.getDaysItems(          new Date(self.endTime).getFullYear(),          self.startTime, self.endTime);        self.fixDaysDateBug();      });      self.$nextTick(() => {        self.dateItem.hoursItem = self.getHoursItems(new Date(self.endTime).getFullYear(),          new Date(self.endTime).getMonth() + 1,          new Date(self.endTime).getDate(),          0, new Date(self.endTime).getHours()); //因为是结束时间,所以时刻要从0-结束时间        self.fixHourDateBug();      });      self.$nextTick(() => {        self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),          new Date(self.endTime).getMonth() + 1,          new Date(self.endTime).getDate(),          new Date(self.endTime).getHours(), self.startTime, self.endTime);        self.fixMinDateBug();      });      return false;    }  }  //如果没有传入开始和结束时间  self.dateItem.monthsItem = self.getMonthItems(selectYear, null, null); //根据当前选中的年份,更新月份列表  self.$nextTick(() => {    // 更新当前选中月份    self.fixMonthDateBug();  });  self.$nextTick(() => {    //根据当前选中的年份和月份,更新天份列表    self.dateItem.daysItem = self.getDaysItems(selectYear, this.selectItem.month.value, null, null);    self.fixDaysDateBug();  });  self.$nextTick(() => {    // 简单粗暴 0-23时    self.dateItem.hoursItem = self.getHoursItems(null, null, null, 0, 23);    self.fixHourDateBug();  });  self.$nextTick(() => {    //根据当前选中的年份,月份,天,更新分份列表    self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);    self.fixMinDateBug();  });  return false;});复制代码

眼尖的小伙伴看出来了,对于重新选中选项的操作,单独分了一个名为fix****DateBug的方法,那我们就继续理解下列表更新,选中切换的思路

以自动切换月份当前选中为例:

fixMonthDateBug() {  if (!this.dateItem.monthsItem[this.selectItem.month.index]) {  // 如果当前选择的月份index没在当前的月份列表里    /*    * 这里要解释一下:这种情况说明当前选中的月份value和index都不在当前的月份列表内。    * 例如:当前选择的是7.31,选中index就是32。如果切换到2月份,月份有28天,index最长29。    * 就找不到32这个index。所以直接赋值2月份最后一天。    * 这是月份的逻辑。其他同理还有“天”,“时”,“分”的同理逻辑。    * 因为年是最大的单位,所以年不设置此逻辑    * */    this.selectItem.month.index = this.dateItem.monthsItem.length - 1;    this.selectItem.month.value = this.dateItem.monthsItem[this.dateItem.monthsItem.length - 1].value  } else { //如果在的话,只更新value值。    this.selectItem.month.value = this.dateItem.monthsItem[this.selectItem.month.index].value  }},复制代码复制代码

这个操作是为了解决:上次选择的index超过本次列表的长度,导致没有对应值问题。

解决思路:也就是当我上次选择7.31日时,本次切换到2月份。然而2月份没有31日,那我们就重新指向选择为2月最后一天。

那么我们放出剩下的“月”,"天",“时”,“分”监听事件(前方大量代码来袭):

//月列表滚动let MonthsScroll = new BScroll(document.getElementsByClassName("datetime--months")[0], this.scrollParam);MonthsScroll.on('scrollEnd', () => {  let selectYear = self.dateItem.yearsItem[YearsScroll.getSelectedIndex()].value;  //选中的月份Value  let selectMonth = self.dateItem.monthsItem[MonthsScroll.getSelectedIndex()].value;  let selectDay = self.selectItem.day.value;  self.selectItem.month.value = selectMonth;  self.selectItem.month.index = MonthsScroll.getSelectedIndex();  if (self.startTime && self.endTime) {    if (MonthsScroll.getSelectedIndex() === 0 && new Date(self.startTime).getFullYear() === parseInt(selectYear)) {      self.$nextTick(() => {        self.dateItem.daysItem = self.getDaysItems(new Date(self.startTime).getFullYear(), new Date(self.startTime).getMonth() + 1, self.startTime, self.endTime);        self.fixDaysDateBug();      });      self.$nextTick(() => {        self.dateItem.hoursItem = self.getHoursItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          new Date(self.startTime).getDate(),          new Date(self.startTime).getHours(), 23);        self.fixHourDateBug();      });      self.$nextTick(() => {        self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          new Date(self.startTime).getDate(),          new Date(self.startTime).getHours(), self.startTime, self.endTime);        self.fixMinDateBug();      });      return false;    } else if (new Date(self.endTime).getMonth() + 1 === parseInt(selectMonth) && new Date(self.endTime).getFullYear() === parseInt(selectYear)) {      self.$nextTick(() => {        self.dateItem.daysItem = self.getDaysItems(new Date(self.endTime).getFullYear(), new Date(self.endTime).getMonth() + 1, self.startTime, self.endTime);        self.fixDaysDateBug();      });      self.$nextTick(() => {        self.dateItem.hoursItem = self.getHoursItems(new Date(self.endTime).getFullYear(),          new Date(self.endTime).getMonth() + 1,          new Date(self.endTime).getDate(),          0, new Date(self.endTime).getHours());        self.fixHourDateBug();      });      self.$nextTick(() => {        self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),          new Date(self.endTime).getMonth() + 1,          new Date(self.endTime).getDate(),          new Date(self.endTime).getHours(), self.startTime, self.endTime);        self.fixMinDateBug();      });      return false;    }  }  self.$nextTick(() => {    self.dateItem.daysItem = self.getDaysItems(selectYear, selectMonth, null, null);    self.fixDaysDateBug();  });  self.$nextTick(() => {    self.dateItem.hoursItem = self.getHoursItems(null, null, null, 0, 24);    self.fixHourDateBug();  });  self.$nextTick(() => {    self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);    self.fixMinDateBug();  });  return false;});//日列表滚动let DaysScroll = new BScroll(document.getElementsByClassName("datetime--days")[0], this.scrollParam);DaysScroll.on('scrollEnd', () => {  self.selectItem.day.value = self.dateItem.daysItem[DaysScroll.getSelectedIndex()].value;  self.selectItem.day.index = DaysScroll.getSelectedIndex();  let selectYear = self.selectItem.year.value;  let selectMonth = self.selectItem.month.value;  let selectDay = self.selectItem.day.value;  if (self.startTime && self.endTime) {    if (new Date(self.startTime).getFullYear() === parseInt(selectYear)      && new Date(self.startTime).getMonth() + 1 === parseInt(selectMonth)      && new Date(self.startTime).getDate() === parseInt(selectDay)) {      self.$nextTick(() => {        self.dateItem.hoursItem = self.getHoursItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          new Date(self.startTime).getDate(),          new Date(self.startTime).getHours(), 23);        self.fixHourDateBug();      });      self.$nextTick(() => {        self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          new Date(self.startTime).getDate(),          new Date(self.startTime).getHours(), self.startTime, self.endTime);        self.fixMinDateBug();      });      return false;    } else if (new Date(self.endTime).getFullYear() === parseInt(selectYear)      && new Date(self.endTime).getMonth() + 1 === parseInt(selectMonth)      && new Date(self.endTime).getDate() === parseInt(selectDay)) {      self.$nextTick(() => {        self.dateItem.hoursItem = self.getHoursItems(new Date(self.endTime).getFullYear(),          new Date(self.endTime).getMonth() + 1,          new Date(self.endTime).getDate(),          0, new Date(self.endTime).getHours());        self.fixHourDateBug();      });      self.$nextTick(() => {        self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),          new Date(self.endTime).getMonth() + 1,          new Date(self.endTime).getDate(),          new Date(self.endTime).getHours(), self.startTime, self.endTime);        self.fixMinDateBug();      });      return false;    }  }  self.dateItem.hoursItem = self.getHoursItems(null, null, null, 0, 24);  self.$nextTick(() => {    self.fixHourDateBug();  });  self.$nextTick(() => {    self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);    self.fixMinDateBug();  });  return false;})//时列表滚动let HoursScroll = new BScroll(document.getElementsByClassName("datetime--hours")[0], this.scrollParam);HoursScroll.on('scrollEnd', () => {  self.selectItem.hour.value = self.dateItem.hoursItem[HoursScroll.getSelectedIndex()].value;  self.selectItem.hour.index = HoursScroll.getSelectedIndex();  let selectYear = self.selectItem.year.value;  let selectMonth = self.selectItem.month.value;  let selectDay = self.selectItem.day.value;  let selectHour = self.selectItem.hour.value;  if (self.startTime && self.endTime) {    if (new Date(self.startTime).getFullYear() === parseInt(selectYear)      && new Date(self.startTime).getMonth() + 1 === parseInt(selectMonth)      && new Date(self.startTime).getDate() === parseInt(selectDay)      && new Date(self.startTime).getHours() === parseInt(selectHour)) {      self.$nextTick(() => {        self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),          new Date(self.startTime).getMonth() + 1,          new Date(self.startTime).getDate(),          new Date(self.startTime).getHours(), self.startTime, self.endTime);        self.fixMinDateBug();      });      return false;    } else if (new Date(self.endTime).getFullYear() === parseInt(selectYear)      && new Date(self.endTime).getMonth() + 1 === parseInt(selectMonth)      && new Date(self.endTime).getDate() === parseInt(selectDay)      && new Date(self.endTime).getHours() === parseInt(selectHour)) {      self.$nextTick(() => {        self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),          new Date(self.endTime).getMonth() + 1,          new Date(self.endTime).getDate(),          new Date(self.endTime).getHours(), self.startTime, self.endTime);        self.fixMinDateBug();      });      return false;    }  }  self.$nextTick(() => {    self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);    self.fixMinDateBug();  });  return false;})//分列表滚动let MinsScroll = new BScroll(document.getElementsByClassName("datetime--mins")[0], this.scrollParam);MinsScroll.on('scrollEnd', () => {  self.selectItem.min.value = self.dateItem.minsItem[MinsScroll.getSelectedIndex()].value;  self.selectItem.min.index = MinsScroll.getSelectedIndex();})复制代码

注意:每一个监听事件,都是重新刷新子时间单位的列表并重新更改选择项。所以代码量从 ”年“ 到 ”分“ 是逐级递减的

剩余的日期选择项更改逻辑:

fixDaysDateBug() {  if (!this.dateItem.daysItem[this.selectItem.day.index]) {    this.selectItem.day.index = this.dateItem.daysItem.length - 1;    this.selectItem.day.value = this.dateItem.daysItem[this.dateItem.daysItem.length - 1].value  } else {    this.selectItem.day.value = this.dateItem.daysItem[this.selectItem.day.index].value  }},fixHourDateBug() {  if (!this.dateItem.hoursItem[this.selectItem.hour.index]) {    this.selectItem.hour.index = this.dateItem.hoursItem.length - 1;    this.selectItem.hour.value = this.dateItem.hoursItem[this.dateItem.hoursItem.length - 1].value  } else {    this.selectItem.hour.value = this.dateItem.hoursItem[this.selectItem.hour.index].value  }},fixMinDateBug() {  if (!this.dateItem.minsItem[this.selectItem.min.index]) {    this.selectItem.min.index = this.dateItem.minsItem.length - 1;    this.selectItem.min.value = this.dateItem.minsItem[this.dateItem.minsItem.length - 1].value  } else {    this.selectItem.min.value = this.dateItem.minsItem[this.selectItem.min.index].value  }},复制代码

好了,到这里一个功能基础功能的时间选择器(DatePicker)就做完了。组件代码在码云上有托管。链接:

emmm.....求各位路过点个小心心呗~~

转载地址:http://afgfl.baihongyu.com/

你可能感兴趣的文章
ThreadPool 线程池
查看>>
AWK 文件处理计数
查看>>
我的友情链接
查看>>
AI技术说:人工智能相关概念与发展简史
查看>>
eclipse启动失败
查看>>
(已解决!)精选30道Java笔试题解答
查看>>
【Python之旅】第七篇(三):使用Redis订阅服务
查看>>
linux远程桌面链接windows
查看>>
TrendMicro:新的APT***针对亚洲和欧洲政府组织,包括中国媒体机构
查看>>
C语言中sizeof与strlen区别2
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
我的友情链接
查看>>
UIWebView加载html网页时使用缓存和清空缓存
查看>>
我的友情链接
查看>>
设计模式学习笔记(六)之策略模式(Strategy)
查看>>
python运行spark脚本程序
查看>>
我的友情链接
查看>>
通过libvirt使用ceph块设备
查看>>
优秀交互设计师成长指南
查看>>