Ion-datetime动态修改值部分周失效,报TypeError错误
使用ion-datetime实现周选择器时出现TypeError错误
实现目标
采用原生JavaScript开发,不依赖Angular、React等框架(必要时可接受jQuery)。借助ion-datetime组件实现周选择器,利用其完整日历展示能力完成周选择功能。核心逻辑:监听ionChange事件,捕获点击的日期,计算该日期所属周的7天,将这7天组成的数组赋值给日历组件的value属性。
问题描述
点击特定周时,会抛出错误:TypeError: Cannot read properties of undefined (reading 'year'),但所有周的处理流程完全一致。
代码
CSS代码
@import url('https://fonts.googleapis.com/css2?family=Lilita+One&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Indie+Flower&display=swap'); :root { --bg-rosa: #f3e1e3; --top1-rosa: #fbb6ad; --top2-rosa: #b4dadf; --top1-rosa-aux: #facec8; --top2-rosa-aux: #d5e7e8; --bg-turquesa: #d5e7e8; --top1-turquesa: #6ccac8; --top2-turquesa: #efb049; --top1-turquesa-aux: #8fd9d8; --top2-turquesa-aux: #f0cb90; --bg-amarillo: #fffdeb; --top1-amarillo: #ffe373; --top2-amarillo: #ffabab; --top1-amarillo-aux: #fff0b3; --top2-amarillo-aux: #ffc7c7; --bg-morado: #ece4ff; --top1-morado: #a4a4eb; --top2-morado: #a1dae6; --top1-morado-aux: #c2c2f2; --top2-morado-aux: #c7ebf2; --bg: var(--bg-morado); --top1: var(--top1-morado); --top1-aux: var(--top1-morado-aux); --top2: var(--top2-morado); --top2-aux: var(--top2-morado-aux); --top-text: #444c53; } body { position: relative; background: var(--bg); padding: 0; margin: 0; } .week { display: grid; grid-template-columns: repeat(7, minmax(10em, 25em)); width: 100%; height: 100%; padding: 1em; } .day { position: relative; flex-grow: 1; height: 100%; } .day::after { content: ""; display: block; width: 100%; height: 100%; background: var(--bg); opacity: 0; position: absolute; top: 0; left: 0; pointer-events: none; } .day:hover::after { opacity: 0.2; } .top { display: flex; align-items:center; justify-content:center; padding: 0.35em; font-family: 'Lilita One', cursive; font-size: min(calc(1em + 1vw), calc(1em + 2vh)); color: var(--top-text); text-align: center; vertical-align: baseline; border-radius: calc(1em + 1vh) calc(1em + 1vh) 0 0; } .content { border-radius: 0 0 calc(1em + 1vh) calc(1em + 1vh); } .info { /* height: 49vh; */ height: calc(49vh - 0.4vw); font-family: 'Indie Flower', cursive; font-weight: 500; font-size: 1.2rem; padding: 0.5rem 0.5rem 0 1rem; overflow-y: scroll; background-color: #ffffff; background-size: 1.5rem 1.5rem; background-image: repeating-linear-gradient(0deg, #d7d7d780, #d7d7d780 1px, #ffffff 1px, #ffffff); } ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-track-piece:end { background: transparent; margin-bottom: 1.5vh; } ::-webkit-scrollbar-thumb { border-radius: 8px; background: #c2c9d2; } .frame { padding: 0 0.25em 0.25em 0.25em; height: calc(100% - min(calc(1em + 1vw), calc(1em + 2vh)) - 2em); } .frame-square { background-color: var(--top1); } .frame-dotted { background-color: var(--top2); } .square { background-position: center; background-color: var(--top1); background-image: linear-gradient(var(--top1-aux) 2px, transparent 2px), linear-gradient(90deg, var(--top1-aux) 2px, transparent 2px); background-size: 1em 0.9em, 1em 0.9em; } .dotted { background-position: center; background-color: var(--top2); background: radial-gradient(circle, transparent 20%, var(--top2) 20%, var(--top2) 80%, transparent 80%, transparent), radial-gradient(circle, transparent 20%, var(--top2) 20%, var(--top2) 80%, transparent 80%, transparent) 17.5px 17.5px, linear-gradient(var(--top2-aux) 1.4px, transparent 1.4px) 0 -0.7px, linear-gradient(90deg, var(--top2-aux) 1.4px, var(--top2-aux) 1.4px) -0.7px 0; background-size: 35px 35px, 35px 35px, 17.5px 17.5px, 17.5px 17.5px; } #calendario { width: 30vw; height: 40vh; margin: 0; margin-left: 1em; margin-bottom: 1em; border-style: solid; border-color: var(--top1); border-radius: 1em; } .ion-color-same { --ion-color-base: var(--top1); --ion-color-contrast: white; } ion-datetime { --background: var(--bg); border-radius: 16px; margin-right: 5em; } table { height: 100%; width: 100%; } #inf { padding: 0; margin: 0; height: 15rem; } #frase { margin: 3rem; font-family: 'Dancing Script', 'Lilita One', cursive; color: var(--top-text); } #frase-container { width: 100%; height: 100%; text-align: center; } #fondo-frase { display: flex; height: calc(100% - 1em); width: calc(100% - 2em); max-height: calc(100% - 1em); max-width: calc(100% - 2em); margin: 1em; margin-top: 0; align-items:center; justify-content:center; } ion-datetime::part(datetime-year){ background: red; }
HTML及JavaScript代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Document</title> <script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script> <script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" /> <link rel="stylesheet" href="style.css"> <script> function valueChanged() { const calendario = document.getElementById('calendario'); if (calendario.value.length != 7) { const last = calendario.value[calendario.value.length - 1]; let date = new Date(last); date = getMonday(date); selectFromMonday(date); } } function getMonday(date) { switch (date.getDay()) { case 2: date.setDate(date.getDate() - 1); break; case 3: date.setDate(date.getDate() - 2); break; case 4: date.setDate(date.getDate() - 3); break; case 5: date.setDate(date.getDate() - 4); break; case 6: date.setDate(date.getDate() - 5); break; case 0: date.setDate(date.getDate() - 6); break; } return date; } async function selectFromMonday(date) { let calendario = document.getElementById('calendario'); let diaIds = ['lunes', 'martes', 'miercoles', 'jueves', 'viernes', 'sabado', 'domingo']; let value = []; for (let i = 0; i < 7; i++) { const dia = document.getElementById(diaIds[i]); value.push(date.getFullYear() + "-" + parseInt(date.getMonth()+1) + "-" + date.getDate()); dia.getElementsByClassName('fecha')[0].value = value[value.length - 1]; dia.getElementsByClassName('content info')[0].innerHTML = ""; date.setDate(date.getDate() + 1); } calendario.value = value; } </script> </head> <body> <table id="tabla"> <tr id="sup"><td> <div class="week"> <div class="day" id="lunes"> <input type="hidden" class="fecha"> <div class="top square">LUNES</div> <div class="content frame frame-square"> <div class="content info"></div> </div> </div> <div class="day" id="martes"> <input type="hidden" class="fecha"> <div class="top dotted">MARTES</div> <div class="content frame frame-dotted"> <div class="content info"></div> </div> </div> <div class="day" id="miercoles"> <input type="hidden" class="fecha"> <div class="top square">MIÉRCOLES</div> <div class="content frame frame-square"> <div class="content info"></div> </div> </div> <div class="day" id="jueves"> <input type="hidden" class="fecha"> <div class="top dotted">JUEVES</div> <div class="content frame frame-dotted"> <div class="content info"></div> </div> </div> <div class="day" id="viernes"> <input type="hidden" class="fecha"> <div class="top square">VIERNES</div> <div class="content frame frame-square"> <div class="content info"></div> </div> </div> <div class="day" id="sabado"> <input type="hidden" class="fecha"> <div class="top dotted">SÁBADO</div> <div class="content frame frame-dotted"> <div class="content info"></div> </div> </div> <div class="day" id="domingo"> <input type="hidden" class="fecha"> <div class="top square">DOMINGO</div> <div class="content frame frame-square"> <div class="content info"></div> </div> </div> </div> </td></tr> <tr><td id="inf"> <table><tr><td> <ion-datetime id="calendario" presentation="date" locale="es-ES" first-day-of-week="1" min="1970-01-01T00:00:00" max="2200-12-31T23:59:59" size="cover" color="same" multiple="true"> </ion-datetime> </td><td id="frase-container"> <div id="fondo-frase"> <h1 id="frase"></h1> </div> </td></tr></table> </td> </tr> </table> <script> let today = new Date(); //today.setTime( today.getTime() - today.getTimezoneOffset() * 60 * 1000 ); let monday = getMonday(today); selectFromMonday(monday); let calen = document.getElementById('calendario'); calen.addEventListener('ionChange', function () { valueChanged() }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者jose_rullva
相关产品推荐
相关产品推荐

