checkvalidity() 触发 stepmismatch 校验,仅在调用时或表单提交时生效,不实时拦截;因浮点误差,如 input.value = "0.3" 后 checkvalidity() 可能返回 false;应使用 parsefloat 和容差判断 delta 是否接近整数。

checkValidity() 触发 stepMismatch 校验
浏览器原生的 step 校验不会实时拦截输入,只在调用 checkValidity() 或表单提交时触发。此时若值不满足 min + n × step(n 为整数),input.validity.stepMismatch 会返回 true。
常见错误现象:
- 用户手动输入
2.15,但step="0.1"→ 提交时报错,但输入过程中无提示 -
input.value = "0.3"后立即调用checkValidity(),却返回false(因浮点误差实际存的是0.30000000000000004)
实操建议:
- 不要依赖
change事件做校验——它不保证值已对齐步长 - 在
submit事件中先调用event.preventDefault(),再检查input.validity.stepMismatch - 调试时可打印:
console.log(input.validity),直接看stepMismatch、badInput、rangeOverflow等字段
手动计算是否符合 step 规则
原生校验受浮点精度干扰,(value - min) % step === 0 在 JS 中不可靠。必须用容差判断。
正确做法是用相对误差比较:
- 读取数值用
parseFloat(input.value),别用字符串直接算 - 计算偏移量:
const delta = (val - min) / step - 检查是否接近整数:
Math.abs(delta - Math.round(delta)) - 若不满足,可自动对齐:
input.value = (min + Math.round(delta) * step).toFixed(precision)
例如 step="0.01" 对应 toFixed(2);step="5" 则用 toFixed(0)。
监听 input 事件做实时规整
想让用户“输不进非法值”,必须用 JS 拦截并重写 value,因为 step 属性本身不阻止输入。
关键点:
- 监听
input(不是change),才能捕获每次按键、粘贴、拖动 - 对空值、非数字字符串(如
"12.34.56")先parseFloat,结果为NaN时清空或设默认值 - 避免无限循环:赋值前判断是否已合规,否则
input.value = ...会再次触发input事件 - 移动端软键盘可能不显示小数点,
step="0.1"下用户根本输不了小数 → 此时建议改用step="any"+ JS 校验
服务端必须二次校验 step 合法性
前端 step 是纯体验层约束,不能替代后端验证。攻击者可绕过所有 HTML 属性和 JS 直接发请求。
后端需做三件事:
- 解析传入数值为浮点或定点数(如金额转为整数分)
- 检查是否满足:
(value - min) % step == 0(用高精度库或整数运算) - 单独校验
min和max边界,不要假设前端已过滤
最容易被忽略的是:当 step="any" 时,后端仍要限制小数位数(如价格最多两位),否则数据库或计算逻辑可能出错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











