首页 > 开发 > JS > 正文

利用原生JavaScript实现造日历轮子实例代码

2024-05-06 16:50:37
字体:
来源:转载
供稿:网友

前言

在日常开发中,大多数都是在和框架打交道,久而久之便遗忘了原生JS的感觉,个人感觉中原生JS基础还是很重要的,所以最近就利用了空余时间造一个轮子出来,虽然以我的水平造出来的轮子质量还是不太可靠的,但是我觉得用来练练手还是不错的,哈哈!!

So, Let's begin!

github:github.com/Zero-jian/p

以下是日历的样子,是有点难看,讲究讲究,重点在于JS部分,嘻嘻!!!

JavaScript,日历,代码

关于日历组件的实现思路

  • 设置默认参数
  • 检查节点参数是否传入,否则抛出错误
  • 动态创建显示本日星期几的横轴
  • 动态创建日历的日子
  • 最后添加一点dom动作就好

先来看看构造函数内容

constructor(options) {    let defaluteOptions = {      element: null, //这是节点      startOfWeek: 1,      strings: {        week: n => {          let map = {            0: '周日',            1: '周一',            2: '周二',            3: '周三',            4: '周四',            5: '周五',            6: '周六',          }          return map[n];        },        templateDay: `<li class="currentMonth">          <span class="dayLabel">            <span class="day"></span>            <span class="unit">日</span>          </span>        </li>`      },      days: {},    }    //赋值默认参数    this.options = Object.assign({}, defaluteOptions, options);    //轮番就调用函数动态创建dom    this.checkOptions()._generateTime()._generateWeekDay()._generateCurrentDay();

初始化创建Calendar类对象的时候设置数值,赋值默认参数以及调用方法来动态创建dom,相信小伙伴们看懂这段代码没压力。

该轮子我全程都是用ES6写的,毕竟程序员还是要跟上潮流的!!

赋值参数后开始轮番调用函数,首先调用的是**this.checkOptions()**方法,检查节点是否存在

checkOptions() {    //如果节点不存在直接抛出错误    if (!this.options.element) {      throw new Error('element is request');    }    return this;  }

接下来就是获取当天的年月日

毕竟是日历,获取当前的年月日当参考还是很重要的

_generateTime() {    let data = new Date(); //时间    let year = this.options.days.year = data.getFullYear(); //年份    let month = this.options.days.month = data.getMonth() + 1; //月份    let day = this.options.days.day = data.getDate(); //日子    this.options.days.countDay = 0; //日历总日子数为7*6=42    this.options.days.noMonth = data.getMonth() + 1; //不变的月份    this.options.days.noYear = data.getFullYear(); //不变的年份    return this;  }

创建星期横轴

  _generateWeekDay() {    let {      startOfWeek,      strings    } = this.options;    let calendar = document.querySelector('.calendar');    let ol = dom.create(`<ol class="weekdays"></ol>`);    calendar.appendChild(ol);    let weekIndex = this.createArray(7, startOfWeek).map((day, i) => {      let li = dom.create(`<li>${strings.week(i)}</li>`);      //判断是否为今天      ol.appendChild(li);    });    return this;  }

dom.create是封装好的方法,传入模板即可创建并返回回来

this.createArray()也是封装好的方法,本函数是创建一个长度为7的数组,为什么长度为7?因为周一到周日的长度为7啊,然后开始使用map映射和遍历来创建节点并添加document.body里面!!!

唔唔唔,去到这里,星期横轴就创建好了,接下来是重点部分了,就是创建对于的星期的日子日历,其实只要掌握逻辑就好了,不过因为我是菜鸡,写的时候也有点掉坑,所以,哈哈,你们对我写的代码参考参考就好了!!

接下来是重点了,就是创建日子

创建日历日子分为三个部分,第一部分是上个月的日子,第二是本月的日子,第三部分是下个月的日子,三个部分所以把它们分别封装起来,嫑相互影响!!

话不多说,贴上代码

  //创建当前月份日子  _generateCurrentDay() {    let date = this.options.days;    let calendar = document.querySelector('.calendar');    let ol = dom.create(`<ol class="days"></ol>`);    let getWeek = this._getWeekWeek(date.year, date.month-1, date.day); //星期几    let getMonth = this._getMonth(date.year, date.month) //月份天数    let getMonthDay = this._getWeekDay(); //几号    date.countDay = 0;    date.countDay += getMonth;    calendar.appendChild(ol);    //创建当月日子模块    let dayIndex = this.createArray(42, this.options.startOfWeek).map((day, i) => {      let li = dom.create(this.options.strings.templateDay);      let span = li.querySelector('.dayLabel>.day');      //判断日历起止,对本月日子进行赋值      if (i >= getWeek && i <= (getMonth + getWeek)) {        span.textContent = i - getWeek;      }      //判断是否为今天      if (i == (getMonthDay + getWeek) && date.noMonth == date.month && date.noYear == date.year) {        li.classList.add('today');      }      ol.appendChild(li);    });    document.querySelector('h1.date').appendChild(dom.create(`<p data-role="time">${date.year}-${date.month}-${date.day}</p>`));    this._generatePrevMonth()._generateNextMonth();  }

创建当前月份日子的逻辑就是首先就是创建一个长度为42的数组,因为6*7=42,数组下标为0至42,然后获取当月的天数以及当月一号时候是星期几,通过计算获取本月天数的下标范围,然后通过循环进行赋值,这样就创建了日历本月的天数

然后是创建上个月的天数

按照惯例,贴上代码

_generatePrevMonth() {    let date = this.options.days;    let year = date.year;    let month = date.month;    let beginWeek = this._getWeekWeek(year,month-1,1);//本月开始星期    let countMonth = this._getMonth(year,month-1);//上月月份天数    let li = document.querySelectorAll('.dayLabel>.day');    beginWeek == 0 ? beginWeek+= 7 : ''; //如果月份开头为星期日,会出bug,这是防止    date.countDay += beginWeek;    this.createArray(beginWeek,this.options.startOfWeek).map((day,i)=>{      if(i<beginWeek) {        //上月总天数-本月开始星期几+1+i        li[i].textContent = countMonth - beginWeek + 1 + i;      }    });     return this;  }

创建上月的日子,首先获取本月一号是星期几,比如是星期三就可以知道前面空的数字分别为星期日、星期一和星期二,上月的天数能占三个位置,所以就创建一个长度为3的数组,然后计算上月的天数,然后通过逻辑判断进行赋值,就是如此~~~

最后就是下一个月的天数

代码 代码 代码

//创建下个月日子_generateNextMonth() {    let date = this.options.days;    let year = date.year;    let month = date.month;    let beginWeek = this._getWeekWeek(year,month,1);//开始星期    let countMonth = this._getMonth(year,month+1);//下月月份天数    let li = document.querySelectorAll('.dayLabel>.day');    //data.countDay统计了上月和本月的日子数总量,直接减去即可    this.createArray(42-date.countDay , this.options.startOfWeek).map((day,i)=>{      li[date.countDay+i].textContent = i+1;    });  }

这个逻辑比较简单,就是用(6*7=42)42减去上月天数和本月天数,剩下的位置为显示下个月的天数,所以就是这样子!!!

把封装好的代码也弄出来吧~~

//dom.create()调用let dom = {  create(html) {    let template = document.createElement('template');    template.innerHTML = html;    return template.content.firstChild;  }}
  //this.createArray()调用  //创建数组节点  createArray(length, fill) {    let array = Array.apply(null, {      length: length    }).map(() => fill);    return array;  }

动作切换部分

切换日子这里相对来说就是比较简单,我直接贴代码,你们一看就懂了

   //上一个月  previousMonth() {    // this.options.days.month -= 1;    this.changeMonth('prev');  }  //下一个月  nextMonth() {    // this.options.days.month += 1;    this.changeMonth('next');  }  //回到今天  resetMonth() {    // this._generateTime();    this.changeMonth('defalut');  }  //封装月份dom  changeMonth(status) {    let date = this.options.days;    switch(status) {      case 'prev': {        --date.month < 1 ? date.year-- ? date.month = 12 : '' : '';        break;      }      case 'next': {        ++date.month > 12 ? date.year++ ? date.month = 1 : '' : '';        break;      }      case 'defalut': {        this._generateTime();        break;      }    }    //移除节点    this._generateCalendar();    //重新添加节点    this._generateCurrentDay();  }

唔唔唔,整个日历组件下来大概就是这样子,整个流程写下来感觉自己的思维还是有所进步的,但是其实我觉得这个轮子代码还是可以再封装封装和完善的,嘻嘻~~

轮子功能比较简单,所以剩下的功能就等待小伙伴们自由发挥了~~

好了,第一次写文章,熬夜写的,突然就有灵感了,不肯睡觉,呵呵,,明天上班肯定是要打瞌睡了,呵呵~~~

本人是小白,从业将近一年,所以代码上有什么错误,请各位大神能够指出指出,嗯嗯,完~~

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对VeVb武林网的支持。


注:相关教程知识阅读请移步到JavaScript/Ajax教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表