maxlength仅对text、search、password、email、tel、url、textarea生效,number等类型忽略;不阻止粘贴、JS修改或提交,须JS监听input/paste/compositionend并裁剪+光标保护,且后端校验不可替代。

maxlength 不是万能开关,它只在特定类型上生效、不阻止粘贴、不校验提交、更不防 JS 修改——用错地方或只靠它,等于没设。
哪些 input 类型真正响应 maxlength
只有文本类控件原生支持:text、search、password、email、tel、url 和 textarea。
-
number、date、range、file、checkbox完全忽略该属性;写上也白写,浏览器直接跳过 -
search虽然支持,但默认maxlength是 524288,几乎等同于不限制,必须显式覆盖 -
textarea行为看似一致,但旧版 Safari(iOS 12 之前)和部分 Android WebView 会静默忽略,不能当真 - 带
contenteditable的div或其他非表单元素加maxlength—— 属性存在,但无任何效果
为什么用户还能粘贴超长内容?
因为 maxlength 只拦截「新增字符」的键盘输入,对粘贴、拖拽、DevTools 修改、JS 赋值完全不设防。
- 用户 Ctrl+V 粘贴 200 字符 → 多数浏览器先插入全部,再触发
input事件,此时value.length已超限 - 移动端尤其明显:Android 键盘常允许粘贴后继续编辑,iOS 则可能禁用部分按键但不阻止粘贴本身
- 监听
paste事件时必须调用event.preventDefault(),否则截断逻辑形同虚设 - 仅监听
input不够——输入法未上屏阶段(如拼音输入中)、语音输入、IME 上屏瞬间都不会触发
如何让长度控制真正落地?
必须用 JavaScript 补足,核心是「覆盖所有修改入口 + 安全裁剪 + 光标保护」。
立即学习“前端免费学习笔记(深入)”;
- 同时监听
input、paste、compositionend三个事件,缺一不可 - 裁剪一律用
String.prototype.slice(0, N),避免substr或正则误切 emoji 代理对(如 ??) - 截断后手动调用
el.setSelectionRange(newLength, newLength),否则光标会跳到末尾,破坏编辑体验 - 不要在
input回调里直接赋值再触发新input,需加标记位或防抖,防止死循环
服务端校验不是“补充”,是唯一可信防线
前端所有限制都可被绕过:curl 请求、禁用 JS、删掉 HTML 属性、甚至改写浏览器内核——只要后端不拦,数据就进库。
- MySQL 的
VARCHAR(255)和前端maxlength="255"不等价:前者按 UTF-8 字节数,后者按 UTF-16 码元数;一个生僻字或复合 emoji 可能占 4 字节但只算 1 个码元 - PHP 必须用
mb_strlen($str, 'UTF-8'),Node.js 得用new TextEncoder().encode(str).length才能对齐字节限制 - 框架如 React/Vue 中,
v-model或value + onChange会覆盖原生maxlength截断,必须在状态更新逻辑里手动检查



















