热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

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

这篇文章主要给大家介绍了关于如何利用原生JavaScript实现造日历轮子的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用JavaScript具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

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

So, Let's begin!

github:github.com/Zero-jian/p…

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

关于日历组件的实现思路

  • 设置默认参数
  • 检查节点参数是否传入,否则抛出错误
  • 动态创建显示本日星期几的横轴
  • 动态创建日历的日子
  • 最后添加一点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: `
  • ` }, 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(`
      `); calendar.appendChild(ol); let weekIndex = this.createArray(7, startOfWeek).map((day, i) => { let li = dom.create(`
    1. ${strings.week(i)}
    2. `); //判断是否为今天 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(`
        `); 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(`

        ${date.year}-${date.month}-${date.day}

        `)); 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 &#63; beginWeek+= 7 : ''; //如果月份开头为星期日,会出bug,这是防止
            date.countDay += beginWeek;
            this.createArray(beginWeek,this.options.startOfWeek).map((day,i)=>{
              if(i
        

        创建上月的日子,首先获取本月一号是星期几,比如是星期三就可以知道前面空的数字分别为星期日、星期一和星期二,上月的天数能占三个位置,所以就创建一个长度为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 &#63; date.year-- &#63; date.mOnth= 12 : '' : '';
                break;
              }
        
              case 'next': {
                ++date.month > 12 &#63; date.year++ &#63; date.mOnth= 1 : '' : '';
                break;
              }
        
              case 'defalut': {
                this._generateTime();
                break;
              }
            }
            //移除节点
            this._generateCalendar();
            //重新添加节点
            this._generateCurrentDay();
          }

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

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

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

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

        总结

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


        推荐阅读
        • 微软头条实习生分享深度学习自学指南
          本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
        • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
          本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
        • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
        • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
        • Android中高级面试必知必会,积累总结
          本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
        • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
        • baresip android编译、运行教程1语音通话
          本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
        • 如何用UE4制作2D游戏文档——计算篇
          篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
        • 使用在线工具jsonschema2pojo根据json生成java对象
          本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
        • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
          原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
        • sklearn数据集库中的常用数据集类型介绍
          本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
        • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
        • Java验证码——kaptcha的使用配置及样式
          本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
        • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
        • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
          本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
        author-avatar
        你去过的地方叫远方
        这个家伙很懒,什么也没留下!
        PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
        Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有