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


Posted in Javascript onMay 08, 2019

前言

在日常开发中,大多数都是在和框架打交道,久而久之便遗忘了原生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();
  }

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

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

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

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

总结

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

Javascript 相关文章推荐
Web层改进II-用xmlhttp 无声息提交复杂表单
Jan 22 Javascript
js二维数组排序的简单示例代码
Jan 24 Javascript
JavaScript动态改变div属性的实现方法
Jul 22 Javascript
基于Node.js实现nodemailer邮件发送
Jan 26 Javascript
BootStrap智能表单实战系列(七)验证的支持
Jun 13 Javascript
详解vuejs之v-for列表渲染
Jun 22 Javascript
JS 组件系列之Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案
Jun 30 Javascript
React如何将组件渲染到指定DOM节点详解
Sep 08 Javascript
浅谈Vuex的状态管理(全家桶)
Nov 04 Javascript
浅谈Layui的eleTree树式选择器使用方法
Sep 25 Javascript
node.js 使用 net 模块模拟 websocket 握手进行数据传递操作示例
Feb 11 Javascript
js实现幻灯片轮播图
Aug 14 Javascript
Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换(推荐)
May 08 #Javascript
vue实现菜单切换功能
May 08 #Javascript
浅谈JS的原型和继承
May 08 #Javascript
vue使用vuex实现首页导航切换不同路由的方法
May 08 #Javascript
微信小程序封装自定义弹窗的实现代码
May 08 #Javascript
Vue.js轮播图走马灯代码实例(全)
May 08 #Javascript
深入浅析vue-cli@3.0 使用及配置说明
May 08 #Javascript
You might like
探讨php中header的用法详解
2013/06/07 PHP
php中base64_decode与base64_encode加密解密函数实例
2014/11/24 PHP
WordPress主题制作中自定义头部的相关PHP函数解析
2016/01/08 PHP
Thinkphp3.2简单解决多文件上传只上传一张的问题
2017/09/26 PHP
PHP简单实现防止SQL注入的方法
2018/03/13 PHP
JS input 数字验证代码
2009/07/30 Javascript
jquery 读取页面load get post ajax 四种方式代码写法
2011/04/02 Javascript
javaScript 动态访问JSon元素示例代码
2013/08/30 Javascript
如何用jQuery实现ASP.NET GridView折叠伸展效果
2015/09/26 Javascript
AngularJs中route的使用方法和配置
2016/02/04 Javascript
使用PHP+JavaScript将HTML页面转换为图片的实例分享
2016/04/18 Javascript
AngularJS中的Promise详细介绍及实例代码
2016/12/13 Javascript
JavaScript中数组的各种操作的总结(必看篇)
2017/02/13 Javascript
bootstrap table使用入门基本用法
2017/05/24 Javascript
JavaScript脚本语言是什么_动力节点Java学院整理
2017/06/26 Javascript
移动端网页开发调试神器Eruda的介绍与使用技巧
2017/10/30 Javascript
angular 表单验证器验证的同时限制输入的实现
2019/04/11 Javascript
在Vue中使用icon 字体图标的方法
2019/06/14 Javascript
vue实现一个6个输入框的验证码输入组件功能的实例代码
2020/06/29 Javascript
JavaScript中数组去重的5种方法
2020/07/04 Javascript
[01:14:34]DOTA2上海特级锦标赛C组资格赛#2 LGD VS Newbee第一局
2016/02/28 DOTA
在Python中利用Pandas库处理大数据的简单介绍
2015/04/07 Python
详解Python编程中对Monkey Patch猴子补丁开发方式的运用
2016/05/27 Python
python通过elixir包操作mysql数据库实例代码
2018/01/31 Python
Python 3.8 新功能来一波(大部分人都不知道)
2020/03/11 Python
通过python 执行 nohup 不生效的解决
2020/04/16 Python
Ubuntu权限不足无法创建文件夹解决方案
2020/11/14 Python
Perfume’s Club澳大利亚官网:西班牙领先的在线美容店
2021/02/01 全球购物
简述索引存取方法的作用和建立索引的原则
2013/03/26 面试题
自荐书模板
2013/12/15 职场文书
致全体运动员广播稿
2014/02/01 职场文书
药品销售内勤岗位职责
2015/04/13 职场文书
联谊活动总结范文
2015/05/09 职场文书
你对自己的信用报告有过了解吗?
2019/07/09 职场文书
go语言基础 seek光标位置os包的使用
2021/05/09 Golang
Python可视化学习之seaborn绘制矩阵图详解
2022/02/24 Python