写日历需要注意的两个问题
- 每周从周几开始,从周日开始还是从周一开始,像苹果上的日历就是从周日开始
从图上看出,不管是从哪天开始,整体的顺序不变 ,这个情况和无缝滚动的组件很像,内容滚出到视图外,自动补充到末尾,就像一个圆环
p1-juejin.byteimg.com/tos-cn-i-k3…
基于这个原理,很容易得到一周七天的数字
// 在 js 中,0 是周日,0 ~ 6 代表周一至周日
const WEEKDAYS = [0, 1, 2, 3, 4, 5, 6]
// 一周只有7天,不会有第8天,所以只要拷贝一次就可以了
const DOUBLE_WEEKDAYS = WEEKDAYS.concat(WEEKDAYS)
/**
* 获取获得一周7天的数字
* @param firstWeekDay 周开始时间
* @return 周数组
*/
function getWeekdays(firstWeekDay = 0) {
if (firstWeekDay === 0) return WEEKDAYS
return DOUBLE_WEEKDAYS.slice(firstWeekDay, firstWeekDay + 7)
}
执行后的结果
获取日历头部,顺便支持国际化
// 简体中文
const zh = {
// 完整名称
weekdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
// 短名称
weekdaysShort: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
// 缩写
weekdaysAbbr: ['日', '一', '二', '三', '四', '五', '六']
}
// 英文
const en = {
// 完整名称
weekdays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
// 短名称
weekdaysShort: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
// 缩写
weekdaysAbbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
}
/**
* 获取一星期的名称列表
*
* @param {Number[]} weekdays 一周7天的数字
*
* @param {Object[]}
*/
function getWeekHead(weekdays, locale) {
return weekdays.map(day => ({
name: locale.weekdays[day],
short: locale.weekdaysShort[day],
abbr: locale.weekdaysAbbr[day],
day: day
}))
}
执行结果
- 每个月的第一天不是从一号开始的
从图上可以看到,月开始和月结束都是不固定的,这该如何处理
只要知道每个月的一号是周几,在往前减去几天,就可以得出日期开始的时间
可能有点绕,看图
在js中 可以通过Date.getDay()方法知道是星期几
因为前面说过,周开始是不固定的(周日开始或周一开始),还要前面的函数才知道要减去几天
每个月的天数不一致,关于闰月的问题,js的Date对象已经帮我们处理好了
接下来就是循环产生数据了
/**
* 获取月份日历
*
* @param {*} year 年
* @param {*} month 月
* @param {Object} options
* @param {Number[]} options.weekdays 一周7天的数组
* @param {Number} [options.firstWeekDay=0] 周开始时间
* @param {Number} [options.visibleWeeksCount=6] 单个日历上显示的周数量
*/
function getMonthCalendar(year, month, options) {
const weekdays = options.weekdays
const cursor = new Date(year, month - 1, 1, 0, 0, 0, 0)
const count = (options.visibleWeeksCount || 6) * 7
// 让时间定位在周开始的时间
cursor.setDate(cursor.getDate() - weekdays.indexOf(cursor.getDay()))
const calendar = []
let week = []
for (let i = 0; i < count; i++) {
if (!(i % 7)) {
week = calendar[i / 7] = []
}
week.push(
// 拷贝时间
new Date(cursor)
)
cursor.setDate(cursor.getDate() + 1)
}
return calendar
}
function format(d) {
return `${d.getFullYear()}-${(d.getMonth() + 1).toString().padStart(2, 0)}-${d.getDate().toString().padStart(2, 0)}`
}
执行结果
然后就是往页面上渲染数据了
代码理解 a指向b[0] b[1].....
// let a = []
// const b = []
// for(let i = 0; i < 42; i ++) {
// if (!(i % 7)) {
// a = b[i / 7] = [] // a = b[0] = []
// }
// a.push(i) === b[0].push(i)
// }
// console.log(b)