如何将MySQL日期查询结果转为可用于日期重复校验的JS数组
假日日期重复校验功能开发问题
- 功能核心需求:开发带假日日期选择的页面,将用户选中的假日日期,与页面表格Date列存储的全量已有日期做比对,校验所选日期是否重复。
已尝试的方案与现存问题
1. 单行比对逻辑
最初编写的校验函数仅能匹配表格第一行的日期值,无法覆盖全量数据,核心代码:
function dateChk(){ var dt1 = document.getElementById('PHDate').value; var dt2 = document.getElementById('phdateadd').value; if (dt1 == dt2) { alert("This date already assigned, please try again."); document.getElementById('phdateadd').value = 0; } }
该逻辑缺陷为仅能校验第一行数据,无法满足全量比对需求。
2. 硬编码数组校验方案
改用硬编码JS数组存储全部已有日期完成校验,代码如下:
<input id="phdateadd" name="phdateadd" type="date" onchange="myFunction()" required> <p id="demo"></p> <script> var dates= ["2021-01-01", "2021-02-12", "2021-02-13", "2021-04-02", "2021-05-01", "2021-05-13", "2021-05-14", "2021-05-26", "2021-05-30", "2021-05-31", "2021-07-06", "2021-07-20", "2021-08-10", "2021-08-31", "2021-09-16", "2021-10-02", "2021-10-19", "2021-11-04", "2021-12-25"]; function checkDate(date) { return date == document.getElementById("phdateadd").value; } function myFunction() { document.getElementById("demo").innerHTML = dates.find(checkDate); var chk = document.getElementById("demo").innerHTML; if ( chk != "undefined" ) { alert("This date already assigned, please try again."); document.getElementById("phdateadd").value = 0;} } </script>
该方案可正常完成校验,但需要手动维护数组内的全部日期值,无法动态同步数据库的最新数据。
3. 数据库拼接字符串直传方案
为实现动态数据同步,编写MySQL查询直接从库表提取日期,自动拼接为数组格式的字符串:
SELECT CONCAT('["',GROUP_CONCAT(phdate SEPARATOR '", "'),'"]') As arrdate FROM table1;
查询返回结果的外观与硬编码数组完全一致:
["2021-01-01", "2021-02-12", "2021-02-13", "2021-04-02", "2021-05-01", "2021-05-13", "2021-05-14", "2021-05-26", "2021-05-30", "2021-05-31", "2021-07-06", "2021-07-20", "2021-08-10", "2021-08-31", "2021-09-16", "2021-10-02", "2021-10-19", "2021-11-04", "2021-12-25"]
将查询返回结果嵌入页面模板,核心代码:
<% phDates.forEach((phDates, index) => { %> <tr><td><p id="phdates" name="phdates" value="<%= phDates.arrdate %>"><%= phDates.arrdate %> <% }) %></p><p id="demo" name="demo">b</p><br><p id="demo1" name="demo1">a</p></td></tr> <script> var dates = document.getElementById("phdates").innerHTML; document.getElementById("demo").innerHTML = dates; </script>
该方案的核心问题为:JS从DOM中读取到的内容是经过渲染的纯字符串,并非可直接操作的数组对象,导致校验逻辑完全失效;尝试用$( "div" ).toArray()从DOM提取值构建数组也未成功。
可行的调整方案
不需要依赖复杂的字符串转义处理,从两个环节调整即可实现动态全量校验:
1. 调整数据库到前端的数据传递链路
不要把拼接好的类数组字符串塞到普通DOM节点的文本内容里做中转:
原SQL拼接的字符串只是外观和数组一致,经过HTML DOM渲染后会被转义处理,哪怕格式看起来正常,实际读取到的也是带特殊字符的纯文本,无法被JS识别为数组结构。
- 后端查询时,不需要手动拼接JSON格式的字符串,直接把查询到的日期列表返回给模板引擎即可
- 模板渲染时,直接把日期列表序列化为合法的JS数组,写入到脚本作用域内,不嵌套到普通HTML元素中:
该方式生成的JS数组结构合法,不存在字符串转义问题。<script> // 借助模板引擎的JSON序列化能力直接输出合法JS数组,不经过DOM中转 const existingHolidays = <%- JSON.stringify(phDates.map(item => item.phdate)) %>; </script>
2. 优化前端校验逻辑
拿到合法的日期数组后,替换原硬编码逻辑,简化校验流程:
function myFunction() { const selectedDate = document.getElementById("phdateadd").value; // 直接用数组内置方法判断日期是否重复,不需要额外DOM读写 const isDuplicate = existingHolidays.includes(selectedDate); if (isDuplicate) { alert("This date already assigned, please try again."); // 清空日期输入框时设为空字符串,设为0会触发输入校验报错 document.getElementById("phdateadd").value = ""; } }
常见踩坑提醒
- 避免把JS对象/数组塞到普通HTML元素的innerHTML中做中转,DOM会对特殊字符做转义,破坏原有数据格式
- 原代码中借助
dates.find()的返回值插入DOM再判断是否存在的逻辑冗余,直接用数组内置的includes()方法判断即可,减少不必要的DOM操作 - 日期类型的输入框,清空值时需要设为空字符串,设为数字0会触发浏览器原生校验报错
内容的提问来源于stack exchange,提问作者FanoFN
相关产品推荐
相关产品推荐

