maxlength 对 type="number" 等类型无效是规范行为,仅对 text、search、url、tel、email、password 和 textarea 生效;需结合 composition 事件、array.from 计数、paste/drop 监听及服务端一致校验来实现可靠长度控制。

maxlength 失效不是 bug,是它本来就不该对某些 type 起作用——比如 type="number"、type="date"、type="file",浏览器直接忽略该属性,连日志都不会打。
为什么 type="number" 加了 maxlength 还能输超长?
HTML 规范明确写死:maxlength 只对 text、search、url、tel、email、password 和 textarea 有效。其他类型(包括 number)不参与长度校验逻辑,value 是字符串,但浏览器根本不读这个属性。
- 现象:用户输入
12345678901(11 位),input.value.length确实是 11,但maxlength="10"完全没反应 - 别试
type="tel"代替——虽然它支持maxlength且唤起数字键盘,但语义错误(手机号 ≠ 任意数字),表单验证会出问题 - 移动端尤其明显:iOS Safari 对
type="number"的软键盘行为更不可控,maxlength无效 + 键盘不自动收起 = 用户体验断层
中文输入法下 input 事件截断总“慢半拍”
拼音还没上屏时,input.value 是空的或只有零散字母,input 事件不触发;一按空格,“中国”两个字突然塞进来,此时才触发事件——但用户已经打了十几键,感知上就是“明明只输了 2 字却提示超限”。
- 必须同时监听
compositionstart和compositionend:前者标记输入法开始组合,后者才是真实字符落定时机 - 只在
!event.isComposing时做截断,否则会打断候选词选择,导致用户无法完成输入 - 用
Array.from(str)替代str.length:确保 emoji、生僻汉字(代理对)被正确计数,避免slice(0, N)截断在中间造成乱码
粘贴、拖拽、DevTools 修改都能绕过 maxlength
原生 maxlength 只拦截部分键盘输入和 Ctrl+V,对右键粘贴、拖放文本、脚本赋值 el.value = longStr 完全无约束力。这不是缺陷,是设计使然——它只是 UI 层的弱提示。
- 监听
paste事件,调用event.preventDefault(),再手动取event.clipboardData.getData('text')截断后插入 - 不要只监听
input:拖拽文本会跳过它,得加drop事件兜底 - 服务端校验必须用和前端一致的计数方式(如
Array.from(str).length),不能直接用str.length或字节长度——否则用户输 97 个字符被截,后端报错“超出 100 字符”,查半天发现是 emoji 代理对没处理
真正难的不是写一行 el.value = el.value.slice(0, N),而是把输入法状态、代理对安全截断、光标位置保持、多端事件兼容这四件事串成一条不掉链子的流水线。漏掉任意一环,用户就会遇到“删不掉最后一个字”“粘贴后光标乱跳”“iOS 上屏即超限”这类问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











