moment是一个js工具库,这个库中封装的是日期时间的方法,功能很全面。可以去moment官网看看,它的中文文档介绍的也很详细,主要是看一下方法的使用。附上官网地址:moment.js官网
模仿的是win10自带的日历,但是功能没有很全面,简单的实现了上下翻更新的效果,选择年份的功能没有实现呢。
简单说下,日历的逻辑问题。
从当前月出发,必须直到当前月的天数,必须知道当前月第一天是星期几。
只有知道了天数和第一天是星期几,才能知道第一天的位置在哪,要显示几天。核心点就是解决这两点,在解决了天数和星期的问题之后,当前月减去1就是上个月,当前月加上1就是下个月。那整体效果就出来了。
获取某月的天数,获取某月第一天是周几等等,moment已经为我们封装好了这些方法,直接使用就可以了。
以下方法都是在moment()返回对象身上的方法
获取当前日期和时间:moment()
获取某月的天数:daysInMonth()
获取某月的第一天:startOf(‘month’)
获取某天是星期几:weekday()
增加时间:add(Number, String)
减去时间:subtract(Number, String)
设置中文的语言环境:locale(‘zh-ch’)
获取星期数据:weekdaysMin()
显示格式:format()。这个是使用最多用处最大的方法,它的参数是令牌,令牌不同日期和时间显示不同。
结构和样式的话比较好搭,最终显示的部分都是通过js部分渲染出来的,就不做解释,后面会把代码附上。
//中文语言环境
moment.locale('zh-cn');
// 一、即时的时间
function nowTime() {
timeDate.innerHTML = moment().format('LTS');
}
nowTime();
setInterval(nowTime, 1000);
timeDay.innerHTML = moment().format("LL")
// 二、星期
let weekArr = moment.weekdaysMin(true); // 根据语言环境获取不同的星期数组
let weekStr = '';
weekArr.forEach(function (ele) {
weekStr += `${ele}`;
});
week.innerHTML = weekStr;
// 日历逻辑:
// 必须知道当前月的天数,当前月第一天星期几
// 某月的天数
function getMonthDays(momentObj) {
return momentObj.daysInMonth();
}
// console.log(getMonthDays(moment())); // 当前月最后一天的数字
// console.log(getMonthDays(moment().subtract(1, 'month'))); // 当前月的上一个月最后一天的数字
// console.log(getMonthDays(moment().add(1, 'month'))); // 当前月的下一个月最后一天的数字
// 某月第一天的星期
// startOf 第一天
// weekday 星期几
function getWeekDays(momentObj) {
return momentObj.startOf('month').weekday(); //
}
// console.log(getWeekDays(moment())); // 当月
// console.log(getWeekDays(moment().add(1, 'month'))); // 下个月
// 三、生成日历
let today = moment();
setDate(today);
封装生成日历方法
首先获取当前月的天数,当前月第一天是周几。英文环境下:[“Su”, “Mo”, “Tu”, “We”, “Th”, “Fr”, “Sa”];中文环境下:[“一”, “二”, “三”, “日”, “五”, “六”, “日”]。
获取周几返回的是数组的索引。
function setDate(m) {
// 获得当前月的天数 和 第一天的星期数
let curDays = getMonthDays(m); // 当前天数
let curWeek = getWeekDays(m.clone()); // 当前月第一天的星期(索引值)
let upDays = getMonthDays(m.clone().subtract(1, 'month')); // 上月的天数
// console.log(curDays, curWeek, upDays);
// 生成的结构
let strDate = '';
// 下个月的起始日期
let nextFirstDate = 0;
for (let i = 0; i < 42; i++) {
// 1. 当前月的上一个月
if (i < curWeek) { // 返回的索引值刚好是上月在当月显示的天数
strDate = `
${upDays}
${strDate}`;
upDays--; // 倒叙显示 30 31
} else if (i >= curDays + curWeek) { //去除掉当月天数+上月天数就是下月天数
// 2. 当前月的下一个月:除去当月最后一天+上月的几天剩余的是下月开始计算
// curWeek 返回值刚好是上月占用的天数
nextFirstDate++;
strDate += `
${nextFirstDate}
`;
} else {
// 3. 当前月
// i-curWeek+1 为当前月的天数
// date()获取日期号
// m.date() == i - curWeek + 1说明这一天是当月当天,添加样式
let currentClass = m.date() == i - curWeek + 1 ? 'current' : '';
if (m.year() != moment().year() || m.month() != moment().month()) {
currentClass = '';
}
strDate += `
${currentClass}>
${i-curWeek+1}
`;
}
}
timeYM.innerHTML = m.format("YYYY年MMM"); // 更新日历头部的年月
dateList.innerHTML = strDate; // 渲染日历
}
// 四、按钮事件
upBtn.onclick = function () {
// 点击切换为上个月
setDate(today.subtract(1, 'month'));
}
downBtn.onclick = function () {
// 点击切换为下个月
setDate(today.add(1, 'month'));
}
//获取农历
// 参数:年 月 日
function getDayCn(year, month, date) {
// 把calendar文件中的calendar对象挂在了window对象上,通过属性调用calendar
// 这样不会更改源文件
let dayCn = window.calendar.solar2lunar(year, month, date);
let result = '';
if (dayCn.IDayCn == '初一') { //如果是月初的话,换成这个月的名字
result = dayCn.IMonthCn;
} else if (dayCn.Term) { //如果有节气的话,换成节气
result = dayCn.Term;
} else if (dayCn.festival) { //如果有节日的话,换成节日
result = dayCn.festival;
} else if (dayCn.lunarFestival) { //如果有中国传统的节日的话,换成传统节日(春节、元宵节、端午节)
result = dayCn.lunarFestival;
} else {
result = dayCn.IDayCn; //都没有的话就是农历
}
return result;
}
修改时间下面的日期,也就是加上农历日期
// 即时的日期
var dayCn = window.calendar.solar2lunar(moment().year(), moment().month() + 1,
moment().date()); //取到农历日期
// 拼接农历日期
timeDay.innerHTML = moment().format("LL") +
' ' + dayCn.IMonthCn + dayCn.IDayCn + ' ' + (dayCn.Term ? dayCn.Term : ''); // 年月
添加日历中对应的农历日期,这里我只把不同月拼接字符串的部分放上。
注意:moment().month()返回值比实际月小1,比如本月是7月,moment().month()返回6,刚好是上月,moment().month()+1是本月,moment().month()+2是下月。
// 1. 当前月的上一个月
if (i < curWeek) {
// 上月 getDayCn(m.year(),m.month(),upDays)
// m.month()返回值与实际值少1
strDate = `
${upDays}
${getDayCn(m.year(),m.month(),upDays)}
${strDate}`;
upDays--;
} else if (i >= curDays + curWeek) { // 31+2=33
// 2. 当前月的下一个月:除去当月最后一天+上月的几天剩余的是下月开始计算
// curWeek 返回值刚好是上月占用的天数
strDate += `
${nextFirstDate}
${getDayCn(m.year(),m.month()+2,nextFirstDate)}
`;
nextFirstDate++;
} else {
// 3. 当前月
// i-curWeek+1 为当前月的天数
let currentClass = m.date() == i - curWeek + 1 ? 'current' : '';
if (m.year() != moment().year() || m.month() != moment().month()) {
currentClass = '';
}
strDate += `
${currentClass}>
${i-curWeek+1}
${getDayCn(m.year(),m.month()+1,i-curWeek+1)}
`;
到此,整个日历就完成了。其实用原生js也可以写,但是比较麻烦,使用js工具库写就相对比较简单了。整个日历的核心逻辑就是天数跟第一天是星期几,解决了这个核心点,日历的问题就解决了。
在没写之前确实决定很难实现,在了解之后,明白了日历的逻辑,实现起来就好多了。
加油!!!!
结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>日历</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div class="calenderBox">
<div class="title">
<p class="timeHMS">10:18:06</p>
<p class="timeYMD">2020年7月29日 六月初九</p>
</div>
<div class="content">
<div class="control">
<div class="timeYM">2020年7月</div>
<div class="arrow">
<span class="up">∧</span>
<span class="down">∨</span>
</div>
</div>
<div class="dateList">
<div class="week">
<!-- <span>一</span>
<span>二</span>
<span>三</span>
<span>四</span>
<span>五</span>
<span>六</span>
<span>日</span> -->
</div>
<ul>
<!-- <li><span>28</span><span>初八</span></li>
<li class="speical"><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li class="current"><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li>
<li><span>28</span><span>初八</span></li> -->
</ul>
</div>
</div>
</div>
<script src="./js/moment-with-locales.js"></script>
<script src="./js/calendar.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
样式:
* {
margin: 0;
padding: 0;
}
body {
background: #333;
margin: 0;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
.calenderBox {
width: 420px;
margin: 100px auto 0;
border: 1px solid #444;
background-color: #2d2d2d;
}
/* title */
.title {
padding: 20px 35px;
border-bottom: 1px solid #535353;
}
.title .timeHMS {
font-size: 40px;
color: #efefef;
}
.title .timeYMD {
font-size: 14px;
color: #999;
}
/* content */
.content {
color: #efefef;
padding: 20px 0;
}
.control {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 35px;
height: 25px;
margin-bottom: 15px;
/* border: 1px solid red;
box-sizing: border-box; */
}
.arrow {
padding-right: 5px;
}
.control .up,
.control .down {
display: inline-block;
transform: scaleX(1.7);
font-size: 20px;
margin-left: 33px;
cursor: pointer;
}
.dateList {
padding: 0 20px;
}
.week {
display: flex;
}
.week span {
height: 40px;
flex: 1 1 auto;
text-align: center;
}
.dateList ul {
display: flex;
flex-wrap: wrap;
}
.dateList ul li {
width: 54px;
height: 54px;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.dateList ul li span:nth-child(2) {
font-size: 14px;
}
.dateList li.speical {
color: #6e6e6e;
}
.dateList li.current {
background-color: #0078d7;
}