为何设置datepicker非工作时段的JS函数会导致部分用户浏览器冻结
问题原因
- 运算逻辑错误生成非法时间格式:你代码中
'' + y.getHours() - 1 + ':'的运算顺序是从左到右,先执行字符串拼接得到字符串类型的小时值,再做减法会隐式转换为数字,当用户时区和你测试环境不一致时,getHours()可能返回0,最终会生成-1:59这类非法的时间值。绝大多数日期选择器组件拿到非法时间格式后,内部的时间遍历、校验逻辑会进入死循环,直接占满浏览器主线程,触发页面无响应提示。 - 冗余规则放大性能损耗:
invalid_a和invalid_b数组内的6个时间完全重复,map遍历后会生成12条完全相同的禁用规则,datepicker需要为每个渲染的日期校验所有规则,如果你配置的日期选择范围较大(比如展示半年/一年的日期),重复规则会成倍提升计算量,低配置设备很容易卡死。 - 时区差异导致预期外的结果:你使用的是UTC格式的时间字符串,调用
getHours()会转为用户本地时间计算,时区和你测试环境差异较大的用户(比如东西十二区),拿到的小时数可能超出0-23的合法范围,同样会触发组件内部逻辑异常。
优化后的实现方案
首先去掉无意义的重复遍历,修复运算优先级问题,统一时间格式避免非法值,优化后代码如下:
// 直接读取固定时段的小时值,无需重复解析相同时间字符串 // 如果你要使用本地时间,把getUTCHours替换为getHours即可 const workStartHour = new Date("2021-03-17T13:00:00.000Z").getUTCHours(); const workEndHour = new Date("2021-03-17T22:00:00.000Z").getUTCHours(); const workDays = ["MO", "TU", "WE", "TH", "FR", "SA"].join(','); // 仅生成2条必要的禁用规则即可 const disableTimeRules = [ // 禁用上班前时段 { start: '00:00', end: `${String(workStartHour - 1).padStart(2, '0')}:59`, recurring: { repeat: 'weekly', weekDays: workDays } }, // 禁用下班后时段 { start: `${String(workEndHour).padStart(2, '0')}:01`, end: '23:59', recurring: { repeat: 'weekly', weekDays: workDays } } ]; console.log(disableTimeRules);
额外优化建议
- 如果工作时段是固定值,不需要通过Date对象解析字符串获取小时,直接写死数值即可,性能更稳定。
- 传入datepicker之前可以先校验时间格式合法性,保证小时范围在0-23、分钟在0-59,避免非法值传入组件。
- 如果后续需要支持多套不同的工作时段,先对时间数组做去重处理后再遍历生成规则,避免生成重复冗余的规则。
内容的提问来源于stack exchange,提问作者Ir0ngirll
相关产品推荐
相关产品推荐

