午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

原生JS實現(xiàn)日歷-CSDN博客

 hzlinhui 2024-07-28
這周寫自己的項目發(fā)現(xiàn)又用到日歷了,加之自己畢業(yè)之后的第一個工作中遇到的任務(wù)也是需要寫個日歷(組員寫了,我就不用寫了)

今天就來好好折騰一下日歷是怎么寫的。

首先,我們看看 windows 的日歷。發(fā)現(xiàn)總共有這么幾個元素。先實現(xiàn)試試。
  • 1.年份的選擇、月份的選擇
  • 2.周一 ~ 周日(周日 ~ 周六)
  • 3.日歷格子 6*7 = 42
從數(shù)據(jù)的角度來分析日歷的實現(xiàn)是比較簡單的
  • 1.我們需要顯示一個當前時間的結(jié)構(gòu) - new Date()
  • 2.我們需要顯示當月的信息 - [星期(周一~周日),日期(1-[28,29,30,31])]
    • 其中我們只要知道了每個月的 1日 是星期幾,就能很容易地擺放后面的日子(萬事開頭難)。
    • 我們最多需要 6 行來顯示我們的日期,因為要考慮周一是星期日的情況 1+7*4 = 29(五行)顯然是不夠的
    • 確定了 6 行之后,我們發(fā)現(xiàn)我們可能需要獲取上個月,和下個月多出來的幾天的擺放位置。
    • 不同年份的不同月的 2月份,我們知道它的日期是不同的,所以我們還需要判斷 平年還是閏年。
  • 3.顯示上個月,下個月的切換。我們發(fā)現(xiàn)需要有個函數(shù)來幫我們更新日歷。

    這里我們就要考慮一下,到底要怎么更新這些 dom 里面的數(shù)據(jù)了,重新刪除插入 dom 肯定是不太好的。

分析完之后,讓我們跟著 新增/修改 一些代碼。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. <style>
  9. .week-item {
  10. display: inline-block;
  11. width: 80px;
  12. height: 40px;
  13. line-height: 40px;
  14. border: 1px solid sandybrown;
  15. text-align: center;
  16. }
  17. .date-item {
  18. display: inline-block;
  19. width: 80px;
  20. height: 40px;
  21. line-height: 40px;
  22. border: 1px solid beige;
  23. text-align: center;
  24. }
  25. </style>
  26. </head>
  27. <body>
  28. <div class="wrapper">
  29. <div class="year-line">
  30. <button id="preMonth" class="year-prev">上一月</button>
  31. <button id="nowYear" class="year-now"></button>
  32. <button id="nowMonth"></button>
  33. <button id="nowDate"></button>
  34. <button id="nextMonth" class="year-next">下一月</button>
  35. </div>
  36. <div id="weekLine" class="week-line"></div>
  37. <div id="dateWrap" class="date-wrap"></div>
  38. </div>
  39. </body>
  40. <script>
  41. // 工具方法 - start
  42. // 1.為了獲得每個月的日期有多少,我們需要判斷 平年閏年[四年一閏,百年不閏,四百年再閏]
  43. const isLeapYear = (year) => {
  44. return (year % 400 === 0) || (year % 100 !== 0 && year % 4 === 0);
  45. };
  46. // 2.獲得每個月的日期有多少,注意 month - [0-11]
  47. const getMonthCount = (year, month) => {
  48. let arr = [
  49. 31, null, 31, 30,
  50. 31, 30, 31, 31,
  51. 30, 31, 30, 31
  52. ];
  53. let count = arr[month] || (isLeapYear(year) ? 29 : 28);
  54. return Array.from(new Array(count), (item, value) => value + 1);
  55. };
  56. // 3.獲得某年某月的 1號 是星期幾,這里要注意的是 JS 的 API-getDay() 是從 [日-六](0-6),返回 number
  57. const getWeekday = (year, month) => {
  58. let date = new Date(year, month, 1);
  59. return date.getDay();
  60. };
  61. // 4.獲得上個月的天數(shù)
  62. const getPreMonthCount = (year, month) => {
  63. if (month === 0) {
  64. return getMonthCount(year - 1, 11);
  65. } else {
  66. return getMonthCount(year, month - 1);
  67. }
  68. };
  69. // 5.獲得下個月的天數(shù)
  70. const getNextMonthCount = (year, month) => {
  71. if (month === 11) {
  72. return getMonthCount(year + 1, 0);
  73. } else {
  74. return getMonthCount(year, month + 1);
  75. }
  76. };
  77. // 工具方法 - end
  78. let weekStr = '日一二三四五六';
  79. weekArr = weekStr.split('').map(item => '星期' + item);
  80. // 插入星期 dom
  81. let weekDomStr = '';
  82. let oFragWeek = document.createDocumentFragment();
  83. weekArr.forEach(item => {
  84. let oSpan = document.createElement('span');
  85. let oText = document.createTextNode(item);
  86. oSpan.appendChild(oText);
  87. oSpan.classList.add('week-item');
  88. oFragWeek.appendChild(oSpan);
  89. });
  90. let weekWrap = document.getElementById('weekLine');
  91. weekWrap.appendChild(oFragWeek);
  92. // 這里獲得我們第一次的 數(shù)據(jù) 數(shù)組
  93. const updateCalendar = (year, month, day) => {
  94. if (typeof year === 'undefined' && typeof month === 'undefined' && typeof day === 'undefined') {
  95. let nowDate = new Date();
  96. year = nowDate.getFullYear();
  97. month = nowDate.getMonth();
  98. day = nowDate.getDate();
  99. }
  100. // 更新一下頂部的年月顯示
  101. document.getElementById('nowYear').innerHTML = year;
  102. document.getElementById('nowMonth').innerHTML = month + 1;
  103. document.getElementById('nowDate').innerHTML = day;
  104. // 生成日歷數(shù)據(jù),上個月的 x 天 + 當月的 [28,29,30,31]天 + 下個月的 y 天 = 42
  105. let res = [];
  106. let currentMonth = getMonthCount(year, month);
  107. let preMonth = getPreMonthCount(year, month);
  108. let nextMonth = getNextMonthCount(year, month);
  109. let whereMonday = getWeekday(year, month);
  110. let preArr = preMonth.slice(-1 * whereMonday);
  111. let nextArr = nextMonth.slice(0, 42 - currentMonth.length - whereMonday);
  112. res = [].concat(preArr, currentMonth, nextArr);
  113. // 上面經(jīng)過我本人的測試是沒有什么問題,接下來就是更新 dom 的信息的問題
  114. let hadDom = document.getElementsByClassName('date-item');
  115. if (hadDom && hadDom.length) {
  116. let domArr = document.getElementsByClassName('date-item');
  117. for (let i = 0; i < domArr.length; i++) {
  118. domArr[i].innerHTML = res.shift();
  119. }
  120. } else {
  121. // 如果之前沒有結(jié)構(gòu)的話
  122. let str = '';
  123. for (let i = 0; i < 6; i++) {
  124. str += '<div class="date-line">';
  125. for (let j = 0; j < 7; j++) {
  126. str += `<span class='date-item'>${res.shift()}</span>`;
  127. if (j === 6) {
  128. str += '</div>';
  129. }
  130. }
  131. }
  132. document.getElementById('dateWrap').innerHTML = str;
  133. }
  134. };
  135. updateCalendar();
  136. // 添加上一月,下一月事件
  137. let oPreButton = document.getElementById('preMonth');
  138. let oNextButton = document.getElementById('nextMonth');
  139. oPreButton.addEventListener('click', function () {
  140. let currentYear = +document.getElementById('nowYear').textContent;
  141. let currentMonth = +document.getElementById('nowMonth').textContent - 1;
  142. let currentDate = +document.getElementById('nowDate').textContent;
  143. if (currentMonth === 0) {
  144. updateCalendar(currentYear - 1, 11, currentDate);
  145. } else {
  146. updateCalendar(currentYear, currentMonth - 1, currentDate);
  147. }
  148. });
  149. oNextButton.addEventListener('click', function () {
  150. let currentYear = +document.getElementById('nowYear').textContent;
  151. let currentMonth = +document.getElementById('nowMonth').textContent - 1;
  152. let currentDate = +document.getElementById('nowDate').textContent;
  153. if (currentMonth === 11) {
  154. updateCalendar(currentYear + 1, 0, currentDate);
  155. } else {
  156. updateCalendar(currentYear, currentMonth + 1, currentDate);
  157. }
  158. });
  159. </script>
  160. </html>
發(fā)現(xiàn)用 dom 直接操作而不是通過 mvvm 框架實現(xiàn)確實還是比較蛋疼的,以下是這次實現(xiàn)的效果。

實現(xiàn)一個功能的時候,從數(shù)據(jù)的層面分析,有時候會比較容易理解

calendar2.png

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約