前言
应用场景是公司的一个每日推荐专题需要加入日历功能,点击日历可以跳转到当日的推荐。
设计图:
关于日历的实现
日历实现的核心是利用js的Date对象(项目代码环境是依赖在vue当中)。
第一步:首页展示
我们首先考虑我们日历的第一页,当前月。
要展示我们的当前月,首先我们需要三个数据:
- 当前年份
- 当前月份
- 月份下的日期列表
这些数据的初始化(注意这里只是初始化,因为在日历的使用过程中,他们是会随着交互而变化的)状态很好获得,前两个数据我们只需要通过:
this.curdate = new Date();
this.calendarMonth = this.curDate.getMonth() + 1; // 注意月份加1
this.calendarYear = this.curDate.getFullYear();
值得一提的是我们的日期数据,因为这里涉及到2个变量,第一个是每个月份的天数是不一样的。第二个是每个月的1号是星期几也是不固定的(而这个星期几,则会影响到显示上,1号应该从哪里开始)。
直接贴上最终的获取列表的代码:
/* 返回当月的日期表 */
getMonthList() {
// new Date()中的最后一个参数为0,表示的是当月的最后一天,
// 因此我们通过这一句获得的就是传入的年月的当月最后一天。
let date = new Date(this.calendarYear, this.calendarMonth, 0);
// 获得当月的最后一天的日期号,就知道了当月有多少天
this.days = date.getDate();
// setDate(1)的作用是把日期变为当月的第一天
date.setDate(1);
// 在通过getDay(),就能知道当月的第一天是星期几
let day = date.getDay();
// 获得1号是星期几后,在日历上做一个偏移,这里我采用的是补0
let delay = day - 1;
// 因为星期天在getDay的返回中是0,固特殊处理
if (day == 0) {
delay = 6;
}
let list = [];
for (let i = 0; i < this.days + delay; i++) {
if (i < delay) {
list.push(0);
} else {
list.push(i - delay + 1)
}
}
return list;
},
// 通过这个函数我们就获得了当月的列表,格式类似于[0,0,0,1,2,3...31]
第二步:响应变化
变化主要分为两个方面:点击左右箭头改变月份,点击具体的日期。
改变月份:
改变月份时我们要做的主要工作是改变我们用于记录时间的变量(使用mvvm框架的好处是我们不需要关注视图层面的改变,只需要专注我们的变量):
changeMonth(flag) {
// flag 记录左右滑动,对应到月份就是加1和减1
this.curDate.setMonth(this.calendarMonth - 1 + flag);
// setNowDate() 函数里面包括了我们每次改变日期时所需要做的工作,比如刷新月份列表(即重新调用getMonthList函数等其他一些功能)
//如果我们要把日历做成一个组件,那么我们的函数中肯定需要触发一个事件钩子以反馈给外部例如:$emit('monthChange')
this.setNowDate();
},
改变日期:
changeDay(day, el) {
// 改变我的当前显示日期
this.curDate.setDate(day);
// clickedMonth是用来记录我当前点击的月份,这个变量只随点击改变,而不随页面翻动改变,主要是用来判断当前日期的样式用的。
this.clickedMonth = this.calendarMonth;
this.clickedYear = this.calendarYear;
// 获取当前日历的推荐数据(具体逻辑不赘述,这里可以进行自己需要的操作)
this.getData(new Date(this.calendarYear, this.calendarMonth - 1, day), true)
this.setNowDate();
},
点击了日期后,我们的样式也会随之改变:
// 计算样式的函数
calDayCls(day) {
let cls = "calendar-li";
/* 查看当前 */
if (day == this.calendarDay && this.calendarYear == this.clickedYear && this.calendarMonth == this.clickedMonth) {
cls += ' calendar-li-active';
}
return cls
}
至此,我们的日历的核心功能就完成了,核心函数如下:
setNowDate // 改变控制当前日历显示的变量
changeMonth // 改变月份
getMonthList // 获取月份日期表
changeDay // 改变日期
calDayCls // 计算当前日期的样式
有了这些核心部分,就基本实现了日历的核心功能,然后就可以在上面添加更多的自定义的功能了,因为很多是涉及到我自己项目中个性化的东西,不具备过多参考价值,固没有在代码体现。