zoukankan      html  css  js  c++  java
  • avalon.js实现一个简易日历

    使用MVVM框架avalon.js实现一个简易日历

     

          最近在做公司内部的运营管理系统,因为与日历密切相关,同时无需触发条件直接显示在页面上,所以针对这样的功能场景,我就用avalon快速实现了一个简易日历,毕竟也是第一次造日历这种轮子,所以这里记录下我当时的一些思路,一来做一些技术总结,二来也是给像我这样第一次做日历的前端工程师一些参考。

          先来一起看下日历的界面:

          日历功能包括:1.显示当前月、上个月后几天、下个月前几天的日期,2.切换到上个月,3.切换到下一个月,4.回到今天,5.点击某天弹出当天的年月日(如2014-10-26),同时不在当前月的日期以更淡的颜色与当前月进行一个区分。

          因为使用avalon进行实现,了解MVVM思想的人都知道,mvvm不操作dom,这是框架内部做的事情,而我们仅仅要做的是操作Mode层,也即数据层。

          这里我用一个数组存储当前一个月的所有日期对象,每一天就是一个对象,这个对象包括年,月,日,时间戳,是否隶属于当前月等。如下所示:

    复制代码
    var caleadar = [
        {
            year : 2014,          // 年份
            month : 10,           // 月份
            date : 1,             // 日
            time : 1414771200000, // 时间戳
            flag : false          // 是否隶属于当前月
        },
        {
            year : 2014,
            month : 10,
            date : 2,
            time : 1414911123564,
            flag : true
        },
        .....
    ];
    复制代码

          得到这样一个保存当前月所有信息的数组之后,因为此时caleadar是一个一维数组,而日历是每7天一行,所以这里要将caleadar转化为一个二维数组,每一个子数组里面保存的是一周的日期信息,这样就可以利用avalon的动态模板引擎进行双重模板渲染,这样一个日历就出来了。

          利用getWeeks函数我们就可以得到存储有当前月所有日期信息的数组,如下:

    复制代码
    function getWeeks(ooo) {
        var dateObj = new Date();
        var year = ooo.getFullYear();
        var month = ooo.getMonth(); //得到今天是几月(0 ~ 11)
        var date = ooo.getDate(); //得到今天是几号 (1 ~ 31)
        //var cur = new Date(year, month, date);
        var cur = new Date(year, month, 1);
        cur.setMonth(month + 1); //改为下一个月,
        cur.setDate(0);//由于日期是1 ~ 31, 0则是退到上一个月的最后一天,于是得到这个月的总天数
        var num = cur.getDate();
        var next = 6 - cur.getDay();
        var dates = avalon.range(1, num + 1);
        dates = dates.map(function(d) {
            return dateObj.getFullYear() === year &&
                dateObj.getMonth() === month &&
                dateObj.getDate() === d ? {
                year: year,
                month: month,
                date: d,
                isToday: true,
                flag: true,
                time: new Date(year, month, d) - 0
            } : {
                year: year,
                month: month,
                date: d,
                flag: true,
                time: new Date(year, month, d) - 0
            };
        });
        cur.setMonth(month);
        cur.setDate(1); //得到当月的第一天
        var prev = cur.getDay(); //0 ~ 6
        cur.setDate(date); //还原
        //补上上一个月的日期
        if (month - 1 < 0) {
            year--;
            month = 11;
            for (var i = 0; i < prev; i++) {
                var curr = new Date(year, month, -1 * i);
                dates.unshift({
                    year: year,
                    month: month,
                    date: curr.getDate() + 1,
                    flag: false,
                    time: curr - 0
                })
            }
        } else {
            for (i = 0; i < prev; i++) {
                curr = new Date(year, month, -1 * i);
                dates.unshift({
                    year: year,
                    month: month - 1,
                    date: curr.getDate(),
                    flag: false,
                    time: curr - 0
                })
            }
        }
        //补上下一个月的日期
        if (month + 1 == 12) {
            year++;
            month = 0;
            for (i = 0; i < next; i++) {
                curr = new Date(year, month, i + 1);
                dates.push({
                    year: year,
                    month: month,
                    date: curr.getDate(),
                    flag: false,
                    time: curr - 0
                })
            }
        } else {
            for (i = 0; i < next; i++) {
                curr = new Date(year, month + 1, i + 1);
                dates.push({
                    year: year,
                    month: month + 1,
                    date: curr.getDate(),
                    flag: false,
                    time: curr - 0
                })
            }
        }
        var ret = [];
        while (dates.length) {//每行七个分组
            ret.push(dates.splice(0, 7));
        }
    
        return ret; //一个二维数组
    }
    复制代码

          这里ooo是getWeeks的唯一参数,它是一个Date对象。

          获取到数据之后,直接在html里面进行数据渲染,日历就出来了,相关日历html如下:

    复制代码
    <div class="game_calendar" ms-controller="caleadarID">
        <div class="current_info">
            <button type="button" ms-click="backToToday">today</button>
            <button type="button" ms-click="prevMonth">prev</button>
            <button type="button" ms-click="nextMonth">next</button>
            <span>{{cyear}}年{{cmonth + 1}}月</span>
        </div>
        <table width="100%" border="0" cellspacing="0" cellpadding="0" class="week_title">
            <tbody>
            <tr valign="bottom">
                <td>日</td>
                <td>一</td>
                <td>二</td>
                <td>三</td>
                <td>四</td>
                <td>五</td>
                <td>六</td>
            </tr>
            </tbody>
        </table>
        <table width="100%" cellpadding="0" cellspacing="1" class="calendar_main">
            <tbody>
            <tr ms-repeat-el="calendar">
                <td ms-class="day_style:elem.flag==true" valign="top" ms-repeat-elem="el" ms-click="alert(elem)">
                    <div class="day_mouse">
                        <div class="day_no" ms-if="elem.isToday!=true">{{elem.date}}</div>
                        <div class="day_no" ms-class="today:elem.isToday==true" ms-if="elem.isToday==true">今天</div>
                    </div>
                </td>
            </tr>
            </tbody>
        </table>
    </div>
    复制代码

          我们可以看到,模板里面运用了大量的以ms-开头的绑定属性和{{}}插值表达式,有的是用来渲染样式,有的是用来绑定事件。这样,一个日历就出来了。

          接下来就是日历的切换功能了,实际上上面三个功能本质都是一样,只要传入getWeeks的参数不同返回不同的数组信息就行。因此在程序初始化是我们先保存几个变量,如下:

    复制代码
    var dateObj = new Date();
    vm.calendar = _private.getWeeks(dateObj); //存储当月日历
    vm.cyear = dateObj.getFullYear();  //当前年份
    vm.cmonth = dateObj.getMonth();   //当前月份
    vm.cdate = dateObj.getDate();     //当前日
    复制代码

          接下来就是相关处理逻辑:

    复制代码
    //上一个月
    vm.prevMonth = function () {
        vm.cdate = 1;
        --vm.cmonth;
        if (vm.cmonth < 0) {
            vm.cyear--;
            vm.cmonth = 11;
        }
        _private.change();
    };
    
    //下一个月
    vm.nextMonth = function () {
        vm.cdate = 1;
        ++vm.cmonth;
        if (vm.cmonth == 12) {
            vm.cyear++;
            vm.cmonth = 0;
        }
        _private.change();
    };
    
    //回到今天
    vm.backToToday = function () {
        var dateObj = new Date();
        vm.cyear = dateObj.getFullYear();
        vm.cmonth = dateObj.getMonth();
        vm.cdate = dateObj.getDate();
        _private.change();
    };
    复制代码

          改变当前年、月、日后,我们只需要调用change函数来改变caleadar数组,change函数如下:

    vm.caleader = _private.getWeeks(new Date(vm.cyear, vm.cmonth, vm.cdate));

          这样,一个简易日历就实现了,从头到尾,我们没有操作一行dom,完全的model操作,是不是很爽?

          这里为了让大家看到更好的日历效果,附上日历源码,欢迎下载,有任何疑问欢迎留言!

          caleadar.zip

     
     
  • 相关阅读:
    [轉]Array of pointer VS. Pointer to Array
    VirtualBox 4.2.4 Network setting
    [轉]Interview
    REMOVE “EVAL(BASE64_DECODE” USING LINUX COMMANDS FROM ALL PHP FILES ACROSS MULTIPLE WORDPRESS
    Virtualbox 掛載共用資料夾,解決掛不起來的問題。
    Web shell in php
    端口轉發映射,突破內網
    String 處理 in Java
    [轉]java学习笔记 【二】 常见错误 Class files on classpath not found or not accessible for
    如何讀取float型態資料在記憶體中的值
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4070188.html
Copyright © 2011-2022 走看看