需要一个基本的日历,不需要太多功能,遂简单封装了一个。可以用rollup打个包,便于以后使用。
- 主体部分
import {
formatDate, getMonthDay, chunk,
} from './utils';
import { weekText, monthText } from './text';
export default class Calendar {
constructor(id, option) {
// todo 参数校验
const currentDate = new Date();
this.id = id; // 渲染到 id
this.option = Object.assign({}, {
year: currentDate.getFullYear(), //年
month: currentDate.getMonth() + 1, //月
weekText, // 星期名数组
monthText, //月名数组
tableName: 'calendar--date_table', //渲染的class
}, option);
this.renderYear = this.option.year;
this.renderMonth = this.option.month;
this.render();
}
next() { //渲染下个月
if (this.renderMonth + 1 > 12) {
this.renderMonth = 1;
this.renderYear += 1;
} else {
this.renderMonth += 1;
}
this.render();
}
pre() { //渲染上个月
if (this.renderMonth - 1 < 1) {
this.renderMonth = 12;
this.renderYear -= 1;
} else {
this.renderMonth -= 1;
}
this.render();
}
getMonthDayArray(year, month) {
const arr = getMonthDay(year, month).map(v => ({
date: v,
formatDate: formatDate(v, 'd', this.monthText, this.weekText),
week: v.getDay(),
}));
const a = arr.map(v => v.formatDate);
return new Array(arr[0].week).concat(a).concat(new Array((6 - arr[arr.length - 1].week) % 6));
}
render() {
const wArry = this.getMonthDayArray(this.renderYear, this.renderMonth);
const str = (() => chunk(wArry, 7).reduce((preV, curV) => `${preV}<tr><td>${curV.join('</td><td>')}</td></tr>`, ''))();
const html = `
<table class="${this.option.tableName}">
<thead>
<tr>
${this.option.weekText.map(v => `<td>${v}</td>`).join('')}
</tr>
</thead>
<tbody>
${str}
</tbody>
</table>
`;
document.getElementById(this.id).innerHTML = html;
}
}
- 公用的配置
export const weekText = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
export const monthText = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
- 工具函数
import { weekText, monthText } from './text';
const firstDay = (y, m) => new Date(y, m - 1, 1); //这两个写法比较简洁,记录
const lastDay = (y, m) => new Date(y, m, 0);
const pad = (n, width, z) => {
const pn = `${n}`;
return pn.length >= width ? pn : new Array(width - pn.length + 1).join(z || '0') + pn;
};
export const chunk = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size));
export const getMonthDay = (y, m) => {
const f = firstDay(y, m);
const l = lastDay(y, m);
let i = f;
const result = [];
const d = 24 * 3600 * 1000;
while (i <= l * 1) {
result.push(i);
i = new Date(i.getTime() + d);
}
return result;
};
export const formatDate = (dt, format) => {
let f = format;
f = f.replace('ss', pad(dt.getSeconds(), 2));
f = f.replace('s', dt.getSeconds());
f = f.replace('dd', pad(dt.getDate(), 2));
f = f.replace('d', dt.getDate());
f = f.replace('mm', pad(dt.getMinutes(), 2));
f = f.replace('m', dt.getMinutes());
f = f.replace('MMMM', monthText[dt.getMonth()]);
f = f.replace('MMM', monthText[dt.getMonth()].substring(0, 3));
f = f.replace('MM', pad(dt.getMonth() + 1, 2));
f = f.replace(/M(?![ao])/, dt.getMonth() + 1);
f = f.replace('DD', weekText[dt.getDay()]);
f = f.replace(/D(?!e)/, weekText[dt.getDay()].substring(0, 3));
f = f.replace('yyyy', dt.getFullYear());
f = f.replace('YYYY', dt.getFullYear());
f = f.replace('yy', (`${dt.getFullYear()}`).substring(2));
f = f.replace('YY', (`${dt.getFullYear()}`).substring(2));
f = f.replace('HH', pad(dt.getHours(), 2));
f = f.replace('H', dt.getHours());
return f;
};
- 使用
<button id="pre">pre</button>
<button id="next">next</button>
<h1 id="renderYM"></h1>
<div id="date"></div>
import Calendar from '@/public/calender';
const calendar = new Calendar('date', {
year: 2019,
month: 2,
weekText: ['周日', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
tableName: 't',
});
const eRenderYM = document.getElementById('renderYM');
const showRenderYM = () => {
eRenderYM.innerHTML = `${calendar.renderYear}--${calendar.renderMonth}`;
};
showRenderYM();
document.getElementById('next').addEventListener('click', () => {
calendar.next();
showRenderYM();
}, false);
document.getElementById('pre').addEventListener('click', () => {
calendar.pre();
showRenderYM();
}, false);