文章目录
- 1、原生web实现
- 效果图
- html
- JavaScript
- style
- vue2实现
- html
- JavaScript
1、原生web实现
效果图
html
<div class="box">
<div class="week">
<div>星期日</div>
<div>星期一</div>
<div>星期二</div>
<div>星期三</div>
<div>星期四</div>
<div>星期五</div>
<div>星期六</div>
</div>
<div class="calendar_box">
<div id="idBox" class="calendar"></div>
</div>
<div class="y_m_box">
<div id="idYBtn" class="y_btn_box"></div>
<div id="idMBtn" class="m_btn_box"></div>
<div id="idShow" class="show_box"></div>
</div>
</div>
JavaScript
let y = undefined,
m = undefined;
// 创建日期
function creationDate(y, m, d) {
let arr = [];
for (let i = 1; i < d + 1; i++) arr.push(calendar.solar2lunar(y, m, i));
return arr;
}
// 准备创建的日期数范围
function createCalendar(y, m) {
let y1 = y,
y2 = y,
y3 = y,
m1 = m - 1,
m2 = m,
m3 = m + 1,
d1 = 0,
d2 = 0,
d3 = 0,
moth = [1, 3, 5, 7, 8, 10, 12],
days = () => y % 2 === 0 ? 29 : 28,
dayss = (val) => moth.includes(val) ? 31 : 30;
if (m === 1) (y1 = y - 1, m1 = 12);
if (m === 12) (y3 = y + 1, m3 = 1);
d1 = m1 === 2 ? days() : dayss(m1);
d2 = m2 === 2 ? days() : dayss(m2);
d3 = m3 === 2 ? days() : dayss(m3);
let arr1 = creationDate(y1, m1, d1),
arr2 = creationDate(y2, m2, d2),
arr3 = creationDate(y3, m3, d3),
len2 = arr2.length,
nWeek1 = arr2[0].nWeek,
nWeek3 = arr2[len2 - 1].nWeek;
nWeek1 = nWeek1 === 7 ? 0 : arr2[0].nWeek;
nWeek3 = nWeek3 === 6 ? 0 : nWeek3 === 7 ? nWeek3 - 1 : 6 - nWeek3;
for (let i = arr1.length - 1; nWeek1 > 0; i--) {
arr2.unshift(arr1[i]);
nWeek1--;
}
for (let i = 0; i < nWeek3; i++) arr2.push(arr3[i]);
return arr2;
}
// 初始化
function init() {
let date = new Date();
y = date.getFullYear();
m = date.getMonth() + 1;
let arr = createCalendar(y, m)
str = '';
for (let i = 0; i < arr.length; i++) {
let item = arr[i],
lunar = '';
lunar = item.IDayCn === '初一' && !item.festival ? item.IMonthCn : item.festival ? item.festival : item.IDayCn;
str += `<div class="item">
<div class="south">${item.cDay}</div>
<div class="lunar" style="color: ${item.festival ? '#0000ff' : ''}">${lunar}</div>
</div>`;
}
idBox.innerHTML = str;
let idYBtnStr = '',
idMBtnStr = '';
for (let i = 2003; i < 2030; i++) idYBtnStr += `<div class="y_item">${i}</div>`;
for (let i = 0; i < 12; i++) idMBtnStr += `<div class="m_item">${i + 1}</div>`;
idYBtn.innerHTML = idYBtnStr;
idMBtn.innerHTML = idMBtnStr;
idShow.innerHTML = `<span>${y}</span> <span>${m}</span>`;
}
// 执行初始化
init();
// 选择年份
idYBtn.onclick = ({ target: { textContent, className } }) => {
y = Number(textContent);
assignment(y, className);
}
// 选择月份
idMBtn.onclick = function ({ target: { textContent, className } }) {
m = Number(textContent);
assignment(m, className);
}
// 赋值
function assignment(val, className) {
if (className === 'm_item' || className === 'y_item') {
idShow.innerHTML = `<span>${y}</span> <span>${m}</span>`;
createCalendar(y, m);
}
}
npm插件下载指令
npm install js-calendar-converter --save
或
cnpm install js-calendar-converter --S
注释
1、在全局定义变量
y
和变量m
,两个变量分别用来存储当前选中的年份和月份,初始值为undefined
。
2、定义名为createCalendar
的函数,此函数是本例的重要函数之一。在本函数中会创建当前月的上月和下一月的所有数据,并且会组合成日历的形式返回准确数据,也就是是说会把数据组成七天的形式返回。本月前部分不够那就不上,后半部分不够也不上,总之会组成35
或42
个数据长度。
第一步
定义三个保存年份值的变量,为什么要定义三个呢?有可能你会想,那年份不都一样吗!可惜年份不一定一样。当传入的月份是1
时,年份就要倒退1
年,并且取上一年的12
月份做值;当传入月份是12
时,年份就要加1
,也就是来年的1
月份值。
第二步
月份也需要定义三个变量保存,当传入的值为7
时,第一个变量保存6
,第二个变量保存7
,第三个变量保存8
。
第三步
同时日期也定义三个变量,不过这三个变量不是真正的村存储日期,而是存储当前月的最大日期值,比如当前月有28
天,那就存28
,如果是30
天,那就存30
,共有四种情况,分别是28
、29
、30
和31
,这些数据用来创建当月的完整日期。
第四步
定义moth
月份数组,数组中存放的是1
到12
月,每个月都是31
天的月份序号。
第五步
定义days
箭头函数用来判断2
月份,因为2
月有平年与闰年之分,需要通过特定的手段处理。
第六步
定义dayss
箭头函数用来判断30
天和31
天的月份,配合第四步的moth
数组来判定。
第七步
处理当前月为1
或12
时的年份值和上月值或下月值。
第八步
根据月份获取当月最大天数,首先判断是否是2
月。
第九步
到上面的第八步时,相邻3
个月的年份、月份和月份最大天数都已经准备好,接下来便是获取对应月份的所有天数值了。
定义名为creationDate
的函数,函数的作用是使用for
循环生成当月天数。函数参数分别是y
、m
和d
,y
表示年份,m
表示月份,d
表示循环结束条件。这一步需要npm
插件辅助,这个插件可以实现阳历和农历之间的相互转换。
第十步
经过第九步之后,我们便拿到了相邻3
个月的所有日期值,里面包括阳历、农历和星期等相关值,把3
个月的日期值分别存到3
个变量中待用。
第十一步
这一步处理星期显示的数据,掐头去尾。定义len2
保存当前月的日期长度,获取当前日期数组第一项和最后一项的星期值,并保存到2
个变量中。
第十二步
nWeek1 === 7 ? 0 : arr2[0].nWeek
当星期等于7
时不需要从上个月获取数据补充,否则需要获取上个对应的数据补齐一个星期,也就是需要让数据从星期日开始补齐,当星期值为7
时说明当前月的1
号正好是星期日。
nWeek3 === 6 ? 0 : nWeek3 === 7 ? nWeek3 - 1 : 6 - nWeek3
当前月结束时需要补齐的数据值,如果当前月最后一天正好是星期六,那么就不需要截取下个月的数据来补齐一个星期;如果当前月最后一天是星期日,那么需要从下个月取6
天来补全当月数据;如果是其他星期值,那么就需要使用6
减去当前星期值。这一步可能会有点晦涩难懂,希望我的解释能帮到你。
第十三步
第十二步我们已经拿到掐头去尾的准确数据,那么我们开始实现掐头去尾的工作吧!掐头会比较麻烦一点,因为需要从数组的末尾开始截取数据,所以i
的初始值是数组长度减1
,并且i
做减减操作,退出循环条件是第十二步中获取的nWeek1
值,循环退出条件是nWeek1--
到-1
,使用unshift
向数组前面添加数据。去尾简单一点,直接循环加加就好,这里使用push
向数组末尾添加数据。至此日历数据模板已创建完成,把最终数据返回即可。
3、关于其他函数不做解析,基本都是渲染相关操作啦!
4、html
不做解释,自行阅读即可。
5、style
不做解释,自行阅读即可。
style
body {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
}
.box {
display: flex;
flex-direction: column;
justify-content: center;
}
.item {
background-color: rgba(255, 165, 0, .1);
padding: 2px 0;
border-radius: 3px;
}
.south {
font-size: 18px;
font-weight: 700;
}
.lunar {
font-size: 16px;
}
.week {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px 60px 60px;
text-align: center;
grid-column-gap: 10px;
font-weight: 800;
}
.calendar_box {
margin-top: 6px;
}
.calendar {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px 60px 60px;
text-align: center;
grid-row-gap: 30px;
grid-column-gap: 10px;
}
.y_m_box {
position: fixed;
left: 50%;
top: 10px;
transform: translate(-50%, 0);
display: flex;
flex-direction: column;
align-items: center;
}
.y_btn_box {
display: grid;
grid-template-columns: 68px 68px 68px 68px 68px 68px 68px 68px 68px;
grid-column-gap: 20px;
grid-row-gap: 20px;
}
.m_btn_box {
width: 600px;
margin-top: 26px;
display: flex;
justify-content: space-between;
}
.y_item,
.m_item {
text-align: center;
background-color: rgba(0, 0, 255, .3);
cursor: pointer;
font-weight: 700;
border-radius: 4px;
padding: 2px 0;
box-sizing: border-box;
}
.y_item {
font-size: 16px;
}
.m_item {
width: 36px;
font-size: 18px;
}
.show_box {
margin-top: 10px;
font-size: 30px;
font-weight: 900;
}