闲时练练技术,主要关注代码可读性与优雅 ?
html部分按照上中下布局来写,没什么难度,就不解释了。。。
<body>
<!-- Mac日历模拟 -->
<div id="calendar">
<div class="bar">
<div class="btn y-center">
<span class="orange"></span>
<span class="yellow"></span>
<span class="green"></span>
</div>
<div class="bar-box y-center calen">
<span>日历</span>
</div>
<div class="bar-box y-center add">
<svg t="1565941276742" class="icon add-svg" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="1987" width="15" height="15">
<path
d="M938.116981 485.111606h-409.793201V75.319429c0-13.715373-11.120268-24.835641-24.835641-24.835641-13.715373 0-24.835641 11.120268-24.835641 24.835641V485.111606H68.859297c-13.715373 0-24.835641 11.120268-24.835641 24.835642s11.120268 24.835641 24.835641 24.835641h409.792177v409.7932c0 13.715373 11.120268 24.835641 24.835642 24.835642 13.715373 0 24.835641-11.120268 24.835641-24.835642V534.783913h409.792177c13.715373 0 24.835641-11.120268 24.835642-24.835642S951.832354 485.111606 938.116981 485.111606z"
p-id="1988" fill="#4e4d4e"></path>
</svg>
</div>
<div class="bar-box y-center bar-menu">
<div><span>日</span></div>
<div><span>周</span></div>
<div class="current-menu"><span>月</span></div>
<div class="clear-border-right"><span>年</span></div>
</div>
<input type="search" class="bar-box y-center search">
<div class="bar-box y-center search">
<div class="s-text">
<svg t="1565948270747" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="2959" width="16" height="16">
<path
d="M963.584 934.912L711.68 683.008C772.096 615.424 808.96 527.36 808.96 430.08 808.96 221.184 638.976 51.2 430.08 51.2S51.2 221.184 51.2 430.08s169.984 378.88 378.88 378.88c97.28 0 185.344-36.864 252.928-97.28l251.904 251.904c4.096 4.096 9.216 6.144 14.336 6.144s10.24-2.048 14.336-6.144c8.192-8.192 8.192-20.48 0-28.672zM430.08 768C243.712 768 92.16 616.448 92.16 430.08S243.712 92.16 430.08 92.16s337.92 151.552 337.92 337.92-151.552 337.92-337.92 337.92z"
p-id="2960"></path>
</svg>
<span>搜索</span>
</div>
</div>
</div>
<div class="weeks">
<div class="week-cur">
</div>
<div class="week-texts">
</div>
</div>
<div class="mains">
</div>
</div>
</div>
<script src="calendar.js"></script>
</body>
下面是重头戏⚠️,js部分。中、下两部分的内容都是通过js渲染的。
开始写js前要先做几个准备
1. 星期
const weeks = "日一二三四五六".split('')
2. 每个月有几天
let monthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
3. 每个月的第一天是星期几
monthOneWeekend = new Date(year, month, 1).getDay()
下面开始渲染
// 渲染星期
const weeks = "日一二三四五六".split('')
let weekTexts = document.querySelector('#calendar .weeks .week-texts');
let weeksDom = []
for (let w of weeks.values()) { // 使用es6 的 values()遍历,直接获取值,比遍历键然后再取值节省性能
weeksDom.push("<div>周" + w + "</div>")
}
weekTexts.innerHTML = weeksDom.join('')
// 填充主体数字
function drawData(qdate) {
if (!qdate) qdate = QDate
// 渲染今天年月
let weekCur = document.querySelector('#calendar .weeks .week-cur');
let weekCurDom = '<span class="cur">' + qdate.year + '年' + (qdate.month + 1) + '月</span><div class="cur-box"><div id="prevMonth" οnclick=btnEvent("prevMonth")> < </div><div id="now" οnclick=btnEvent("now")>今天</div><div id="laterMonth" οnclick=btnEvent("laterMonth")> > </div></div>'
weekCur.innerHTML = weekCurDom
// 前面空几天
let year = qdate.year,
month = qdate.month,
day = qdate.day,
monthOneWeekend = new Date(year, month, 1).getDay(),
monthday = monthDays[month]
let prevSpace = monthOneWeekend === 7 ? 0 : monthOneWeekend
// 判断闰年,更改闰年 2 月的天数
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
monthDays[1] = 29
}
// 渲染主体数据
// 将框和文字一起渲染?框和文字分开渲染?
// 选前者
let mains = document.querySelector('.mains')
mains.innerHTML = ""
let dayDom = [],
dayClaz = 'day'
function claz(claz, i) {
return i != 0 && i % 7 == 0 ? dayClaz + ' clear-border-right' : dayClaz // 清除边框
}
function numClaz(currentDay) { // 判断是否是今天
return year === (currentDate().year) && month === (currentDate().month) && currentDay === (currentDate().day) ? "current-num" : ""
}
// 空白
for (let i = 0; i < prevSpace; i++) {
clazs = claz(claz, i + 1)
dayDom.push('<div class="' + clazs + '"></div>')
}
// 主体
for (let i = 1; i < monthday + 1; i++) {
clazs = claz(claz, i + prevSpace)
dayDom.push('<div class="' + clazs + '"><div><span class="num ' + numClaz(i) + '">' + i + '</span><span>日</span></div></div>')
// dayDom.push('<div class="' + clazs + '">'+i+'</div>')
}
// 剩余空白
for (let i = 0; i < (42 - monthday - prevSpace); i++) {
clazs = claz(claz, i + monthday + prevSpace + 1)
dayDom.push('<div class="' + clazs + '"></div>')
}
mains.innerHTML = dayDom.join('')
}
在全局中维护了一个日期对象
let currentDate = function (date) {
if (date == undefined || date == null) date = new Date()
return {
year: date.getFullYear(),
month: date.getMonth(),
day: date.getDate()
}
}
// 维护一个全局的年月对象,初始值为今天
let QDate = {
year: currentDate().year,
month: currentDate().month,
day: currentDate().day,
prevMonth: function () {
if (this.month === 0) {
this.year--;
this.month = 11;
} else {
this.month--;
}
},
laterMonth: function () {
if (this.month === 11) {
this.year++;
this.month = 0;
} else {
this.month++
}
},
current: function () {
this.year = currentDate().year,
this.month = currentDate().month,
this.day = currentDate().day
}
}
完成效果图长这样 ?
项目github地址: https://github.com/yseventeen/Mac-calendar