這周寫自己的項目發(fā)現(xiàn)又用到日歷了,加之自己畢業(yè)之后的第一個工作中遇到的任務(wù)也是需要寫個日歷(組員寫了,我就不用寫了)
今天就來好好折騰一下日歷是怎么寫的。
首先,我們看看 windows 的日歷。發(fā)現(xiàn)總共有這么幾個元素。先實現(xiàn)試試。
- 1.年份的選擇、月份的選擇
- 2.周一 ~ 周日(周日 ~ 周六)
- 3.日歷格子 6*7 = 42
從數(shù)據(jù)的角度來分析日歷的實現(xiàn)是比較簡單的
分析完之后,讓我們跟著 新增/修改 一些代碼。
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> border: 1px solid sandybrown; <button id="preMonth" class="year-prev">上一月</button> <button id="nowYear" class="year-now"></button> <button id="nowMonth"></button> <button id="nowDate"></button> <button id="nextMonth" class="year-next">下一月</button> <div id="weekLine" class="week-line"></div> <div id="dateWrap" class="date-wrap"></div> // 1.為了獲得每個月的日期有多少,我們需要判斷 平年閏年[四年一閏,百年不閏,四百年再閏] const isLeapYear = (year) => { return (year % 400 === 0) || (year % 100 !== 0 && year % 4 === 0); // 2.獲得每個月的日期有多少,注意 month - [0-11] const getMonthCount = (year, month) => { let count = arr[month] || (isLeapYear(year) ? 29 : 28); return Array.from(new Array(count), (item, value) => value + 1); // 3.獲得某年某月的 1號 是星期幾,這里要注意的是 JS 的 API-getDay() 是從 [日-六](0-6),返回 number const getWeekday = (year, month) => { let date = new Date(year, month, 1); const getPreMonthCount = (year, month) => { return getMonthCount(year - 1, 11); return getMonthCount(year, month - 1); const getNextMonthCount = (year, month) => { return getMonthCount(year + 1, 0); return getMonthCount(year, month + 1); weekArr = weekStr.split('').map(item => '星期' + item); let oFragWeek = document.createDocumentFragment(); weekArr.forEach(item => { let oSpan = document.createElement('span'); let oText = document.createTextNode(item); oSpan.appendChild(oText); oSpan.classList.add('week-item'); oFragWeek.appendChild(oSpan); let weekWrap = document.getElementById('weekLine'); weekWrap.appendChild(oFragWeek); // 這里獲得我們第一次的 數(shù)據(jù) 數(shù)組 const updateCalendar = (year, month, day) => { if (typeof year === 'undefined' && typeof month === 'undefined' && typeof day === 'undefined') { let nowDate = new Date(); year = nowDate.getFullYear(); month = nowDate.getMonth(); document.getElementById('nowYear').innerHTML = year; document.getElementById('nowMonth').innerHTML = month + 1; document.getElementById('nowDate').innerHTML = day; // 生成日歷數(shù)據(jù),上個月的 x 天 + 當月的 [28,29,30,31]天 + 下個月的 y 天 = 42 let currentMonth = getMonthCount(year, month); let preMonth = getPreMonthCount(year, month); let nextMonth = getNextMonthCount(year, month); let whereMonday = getWeekday(year, month); let preArr = preMonth.slice(-1 * whereMonday); let nextArr = nextMonth.slice(0, 42 - currentMonth.length - whereMonday); res = [].concat(preArr, currentMonth, nextArr); // 上面經(jīng)過我本人的測試是沒有什么問題,接下來就是更新 dom 的信息的問題 let hadDom = document.getElementsByClassName('date-item'); if (hadDom && hadDom.length) { let domArr = document.getElementsByClassName('date-item'); for (let i = 0; i < domArr.length; i++) { domArr[i].innerHTML = res.shift(); for (let i = 0; i < 6; i++) { str += '<div class="date-line">'; for (let j = 0; j < 7; j++) { str += `<span class='date-item'>${res.shift()}</span>`; document.getElementById('dateWrap').innerHTML = str; let oPreButton = document.getElementById('preMonth'); let oNextButton = document.getElementById('nextMonth'); oPreButton.addEventListener('click', function () { let currentYear = +document.getElementById('nowYear').textContent; let currentMonth = +document.getElementById('nowMonth').textContent - 1; let currentDate = +document.getElementById('nowDate').textContent; if (currentMonth === 0) { updateCalendar(currentYear - 1, 11, currentDate); updateCalendar(currentYear, currentMonth - 1, currentDate); oNextButton.addEventListener('click', function () { let currentYear = +document.getElementById('nowYear').textContent; let currentMonth = +document.getElementById('nowMonth').textContent - 1; let currentDate = +document.getElementById('nowDate').textContent; if (currentMonth === 11) { updateCalendar(currentYear + 1, 0, currentDate); updateCalendar(currentYear, currentMonth + 1, currentDate);
發(fā)現(xiàn)用 dom 直接操作而不是通過 mvvm 框架實現(xiàn)確實還是比較蛋疼的,以下是這次實現(xiàn)的效果。
實現(xiàn)一個功能的時候,從數(shù)據(jù)的層面分析,有時候會比較容易理解
|