利用原生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: `<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();
    }
复制代码唔唔唔,整个日历组件下来大概就是这样子,整个流程写下来感觉自己的思维还是有所进步的,但是其实我觉得这个轮子代码还是可以再封装封装和完善的,嘻嘻~~
轮子功能比较简单,所以剩下的功能就等待小伙伴们自由发挥了~~
好了,第一次写文章,熬夜写的,突然就有灵感了,不肯睡觉,呵呵,,明天上班肯定是要打瞌睡了,呵呵~~~
本人是小白,从业将近一年,所以代码上有什么错误,请各位大神能够指出指出,嗯嗯,完~~

作者:茉莉灬纯洁的白
链接:https://juejin.im/post/5cd1aa3a6fb9a0323b7e5e5c
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

(0)

相关推荐

  • js css+html实现简单的日历

    web页面中很多地方都会用到日历显示,选择等,本文用html.css.javascript实现简单的日历.完成以后的效果与页面左侧的效果差不多,可以切换上个月.下个月.也可以根据实际情况进行扩展. html html部分比较简单,声明一个div,具体的html用javascript生成.整体内容大概是这样的: <!doctype html> <html> <head> <meta charset='utf-8'> <link rel='styleshe

  • javascript html实现网页版日历代码

    本文实例为大家分享了网页版日历代码,供大家参考,具体内容如下 效果图: 实现代码: <html> <head> <link rel="stylesheet" type="text/css" href="Skin.css"> <style> <!-- table{ text-align: center } --> </style> </head> <body&

  • 简约JS日历控件 实例代码

    运行结果如下: 复制代码 代码如下: <script type="text/javascript" language="javascript">function choose_date_czw(date_id,objtd){if(date_id=="choose_date_czw_close"){    document.getElementByIdx_x_x("choose_date_czw_id").style

  • 纯js简单日历实现代码

    复制代码 代码如下: <!doctype html> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css"> body,ul,li,h2,p { margin:0px; pa

  • JS学习之一个简易的日历控件

    这个日历控件类似于园子用的日历,如下图: 这种日历控件实现起来不难,下面简单分析下我的思路: 首先,是该控件的可配置项: 复制代码 代码如下: ... settings: { firstDayOfWeek: 1, baseClass: "calendar", curDayClass: "curDay", prevMonthCellClass: "prevMonth", nextMonthCellClass: "nextMonth&quo

  • js编写当天简单日历效果【实现代码】

    之前一直很想用javascript写一个日历,但是因为完全没有好的思路, 所以迟迟没有尝试.最近在网上刚好看到用javascript编写的简单日历的例子,代码量虽然不大, 但是我觉得很好地阐述了js日历的实现原理.自己也尝试着做了一下,收获蛮大,掌握了基本的实现原理后,再想增加更多的功能,完全就可以自由发挥了,先在这里分享一下吧,有兴趣的可以试试! 一.表格行数问题 既然要显示日期表格的话,首先得知道这个表格有多少行多少列,列数是已经确定的,从星期天(日历上第1列是星期天)到星期六一共7列.要解

  • js日历控件(可精确到分钟)

    .menu_iframe{position:absolute; visibility:inherit; top:0px; left:0px; width:170px; z-index:-1; filter: Alpha(Opacity=0);} .cal_table{ border:#333333 solid 1px; border-collapse:collapse; background:#ffffff; font-size:12px} .cal_table td{ border:1px #

  • JS日历 推荐

    两年前写过一个日历,可是兼容性不好. 这次重新写了一次.  兼容多种浏览器  了解了不少东东,特别是对于W3C标准化.  如 FF和IE 对box模型的理解不同  box.style{width:100;border 1px;}  ie理解 为 box.width = 100  ff 理解 为 box.width = 100 + 1*2 = 102  可以使用这种方法使两种浏览器都可以正常浏览  box.style{width:100!important; width /**/:120px;bo

  • 很好用的js日历算法详细代码

    复制代码 代码如下: <script type="text/javascript">         var lunarInfo = new Array( 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2,

  • 推荐一个小巧的JS日历

    脚本的核心就是DateAdd函数,点击下面的演示看看效果: 查看演示 调用方法很简单, 第一步:在页面顶部包含calenderJS.js文件: <script src="path/to/calenderJS.js"></script> 点击下载这个js文件 第二步:给你的输入框增加onfocus事件属性: <input type="text" onfocus="HS_setDate(this)"> HS_set

随机推荐