
开始我的博客-
日历控件太多了,为什么我们必须创建另一个轮子?
由于大多数日历控件用于选择日期,因此需要在日历上显示各种内容. 这样的日历控件很少,并且在试用后不能令人满意.
因此日历 部件 提取,重新创建一个滚轮,现在带您使用以前完成的组件机制来开发日历控件.
需求
只需按如下方式组织需求:
首先,让我们看一下系统随附的日历,以了解日历的特征.

一个月中有28到31天,但是为了确保结构完整,日历中的上个月和下个月会有一些日期. 总结起来,一个月内的显示必须正好是6周.
然后,只要获得当前月份的开始日期,就可以绘制日历.
如何在当前月份的日历视图中计算开始日期?上面已经对其进行了分析. 为了确保完整性,它会显示上个月的天数,因此仅需从该月的第一天开始计算.
开始日期 = 当月1号的日期 - 当月1号的星期
结束日期 = 开始日期 + 42天
这个问题很清楚. 我觉得实现这样的日历没有很大的障碍. 让我们开始建设吧!
首先构建如下所示的基本结构
其中:

脚部区域用于放置实际使用中的任何逐项内容. 菜单区域用于切换日期时弹出的面板
初始化日历结构后,您可以开始绘制日历.
首先完成开始时间和结束时间的计算
{
// 初始化当前月份的开始日期和结束日期
_initStartEnd: function () {
// 当月1号
var currMonth = moment(this.currMonth, 'YYYY-MM'),
// 当月1号是周几 the ISO day of the week with 1 being Monday and 7 being Sunday.
firstDay_weekday = currMonth.isoWeekday(),
startDateOfMonth,
endDateOfMonth;
if (!this.dayStartFromSunday) {
// 开始为周一 则向前减少周几的天数-1即为 开始的日期
startDateOfMonth = currMonth.subtract(firstDay_weekday - 1, 'day');
} else {
// 开始为周日 则直接向前周几的天数即可
startDateOfMonth = currMonth.subtract(firstDay_weekday, 'day');
}
endDateOfMonth = startDateOfMonth.clone().add(41, 'day');
this.startDateOfMonth = startDateOfMonth;
this.endDateOfMonth = endDateOfMonth;
}
}
因为必须处理多个日期,并且在JavaScript中处理日期时,不同的浏览器存在很大差异,因此您可以使用moment.js统一处理日期.
由于使用习惯的不同,无法确定一周的开始时间是星期一还是星期天,因此只需将其用作配置即可.
一个月的开始日期和结束日期已在上面进行了计算,因此只需使用遍历进行绘制即可.
由于我们使用表格实现,因此需要按行绘制.

实现如下:
{
// 日历可变部分的渲染
_render: function () {
this._initStartEnd();
var weeks = 6,
days = 7,
curDate = this.startDateOfMonth.clone(),
tr;
var start = this.startDateOfMonth.format('YYYY-MM-DD'),
end = this.endDateOfMonth.format('YYYY-MM-DD');
// 清空 并开始新的渲染
this._clearDays();
this._renderTitle();
for (var i = 0; i < weeks; ++i) {
tr = document.createElement('tr');
tr.className = 'ep-calendar-week';
this._daysBody.appendChild(tr);
for (var j = 0; j < days; ++j) {
// 渲染一天 并递增
this._renderDay(curDate, tr);
curDate.add(1, 'day');
}
}
},
// 每天的渲染
_renderDay: function (date, currTr) {
var td = document.createElement('td'),
tdInner = document.createElement('div'),
text = document.createElement('span'),
day = date.isoWeekday(),
// 返回的月份是0-11
month = date.month() + 1;
tdInner.appendChild(text);
td.appendChild(tdInner);
td.className = 'ep-calendar-date';
tdInner.className = 'ep-calendar-date-inner';
// 完整日期
td.setAttribute('data-date', date.format('YYYY-MM-DD'));
// 对应的iso星期
td.setAttribute('data-isoweekday', day);
// 周末标记text.className
if (day === 6 || day === 7) {
td.className += ' ep-calenday-weekend';
}
// 非本月标记
// substr 在ie8下有问题
// if (month != parseInt(this.currMonth.substr(-2))) {
if (month != parseInt(this.currMonth.substr(5), 10)) {
td.className += ' ep-calendar-othermonth';
}
// 今天标记
if (this.today == date.format('YYYY-MM-DD')) {
td.className += ' ep-calendar-today';
}
// 每天渲染时发生 还未插入页面
var renderEvent = this.fire('cellRender', {
// 当天的完整日期
date: date.format('YYYY-MM-DD'),
// 当天的iso星期
isoWeekday: day,
// 日历dom
el: this.el,
// 当前单元格
tdEl: td,
// 日期文本
dateText: date.date(),
// 日期class
dateCls: 'ep-calendar-date-text',
// 需要注入的额外的html
extraHtml: '',
isHeader: false
});
// 处理对dayText内容和样式的更改
text.innerText = renderEvent.dateText;
text.className = renderEvent.dateCls;
// 添加新增内容
if (renderEvent.extraHtml) {
jQuery(renderEvent.extraHtml).appendTo(tdInner);
}
currTr.appendChild(renderEvent.tdEl);
// 每天渲染后发生 插入到页面
this.fire('afterCellRender', {
date: date.format('YYYY-MM-DD'),
isoWeekday: day,
el: this.el,
tdEl: td,
dateText: text.innerText,
dateCls: text.className,
extraHtml: renderEvent.extraHtml,
isHeader: false
});
}
}
从开始日期开始直接绘制42天.
为灵活起见,在绘制的不同时间触发不同的事件,并且在使用时可以绑定相应的事件,并可以在其中执行个性化操作.
为方便和灵活起见,在绘制日期时,将日期和星期属性直接添加到相应的dom中.
在此过程中,您需要标记日期是否为周末,是否为本月,是否已选择,是否为今天等等.
除上述内容外,还绘制了年份和月份选择,标题等. 这些实际上是对现有dom元素的更改,因此不会进行扩展.
上面已基本绘制了日历. 实际上,切换月份更容易. 只需根据新的月份重新计算开始日期,清除原始内容日历 部件 提取,然后重新绘制即可.

{
// 设置月份
setMonth: function (ym) {
var date = moment(ym, 'YYYY-MM');
if (date.isValid()) {
var oldMonth = this.currMonth,
aimMonth = date.format('YYYY-MM');
// 月份变动前
this.fire('beforeMonthChange', {
el: this.el,
oldMonth: oldMonth,
newMonth: aimMonth
});
this.currMonth = aimMonth;
this.render();
// 月份变动后
this.fire('afterMonthChange', {
el: this.el,
oldMonth: oldMonth,
newMonth: aimMonth
});
} else {
throw new Error(ym + '是一个不合法的日期');
}
}
}
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-233410-1.html
好漂亮