maxlength仅对text、search、url、tel、email、password和textarea有效,对number、date等类型无效;不拦截粘贴、不兼容受控组件、不参与表单校验,服务端必须二次校验。

maxlength 限制不住输入,不是你写错了,而是它根本就不是“万能锁”——它只在特定类型上起作用,且对粘贴、框架受控、辅助平面字符等场景天然失效。
哪些 input type 支持 maxlength?
只对以下类型生效:text、search、url、tel、email、password 和 textarea。
-
number、date、range、checkbox等类型完全忽略maxlength—— 浏览器不报错也不执行,写了等于白写 - 常见翻车现场:
<input type="number" maxlength="4">,用户仍可输入123456789或粘贴超长数字串 - 想限制数字位数?改用
min/max+ JS 监听input事件截断,或换type="text" inputmode="numeric"配合pattern="\d{4}"
textarea 的 maxlength 为什么粘贴时失效?
textarea 虽支持 maxlength,但浏览器对粘贴(paste)行为的拦截并不统一:
- 手动输入到上限后,键盘输入被拦截;但 Ctrl+V 粘贴一段超长文本,多数浏览器仍会插入全部内容,再触发
input事件 - 换行符
\n算 1 个字符,不是 2 个;一个 emoji(如 ??)占 2 个 UTF-16 码元,maxlength="10"实际只能输 5 个 - 若需真正拦截粘贴,必须监听
paste事件,在event.clipboardData.getData('text')中提前截断,并调用event.preventDefault()
React/Vue 里 maxlength 为啥不工作?
框架的受控组件(controlled component)会接管 value,导致原生 maxlength 截断逻辑被覆盖:
- React 中写
<input maxlength="{10}" value="{val}" onchange="{...}">,即使用户敲第 11 个字符,框架也会把value设回前 10 位,但光标可能跳到末尾、中间状态闪烁 - Vue 的
v-model同理:仅靠:maxlength="10"不起作用,得在@input中手动event.target.value = event.target.value.slice(0, 10) - 更稳妥的做法:监听
input事件,检查el.value.length > el.maxLength,截断后用setSelectionRange恢复光标位置
服务端为什么必须校验长度?
maxlength 是纯前端体验层约束,没有任何安全意义:
- 禁用 JS、删掉 DOM 属性、用 curl 直接 POST,都能绕过所有前端限制
- 表单提交时,
form.checkValidity()默认不检查maxlength,只认required、pattern、min/max等显式验证属性 - 后端必须按业务要求重新校验:比如 MySQL
VARCHAR(20)字段,不能只信前端传来的 20 字符——UTF-8 下一个 emoji 占 4 字节,20 个字符可能远超 20 字节
真正容易被忽略的点是:**“字符数”和“字节数”不是一回事,而数据库、日志、协议层往往按字节算限额。**maxlength 既不保证字节数,也不保证用户感知的“字”,它只是按 UTF-16 码元做粗粒度拦截。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











