要用 readonly 还是 disabled,关键看后端是否需要接收该字段值:需接收用 readonly,不需则用 disabled;disabled 的字段不参与表单提交,readonly 则正常提交。

该用 readonly 还是 disabled,核心就看一件事:后端要不要收到这个字段的值。要,就用 readonly;不要,才用 disabled。其他所有差异——能不能聚焦、复制、样式变化——都是围绕这个根本逻辑展开的。
表单提交时字段值会不会发到后端?
这是最常踩的坑,也是唯一不可妥协的判断依据。
-
disabled的控件完全不参与表单序列化:FormData、form.submit()、form.serialize()、URL 查询参数里都找不到它,哪怕 DOM 里明明有value="123" -
readonly的控件值照常提交,后端能正常收到name=123,和普通可编辑输入框行为一致 - 管理后台编辑页里把用户 ID 字段写成
<input name="id" value="789" disabled>,上线后接口报“缺少必传参数”,基本就是这个原因
用户能不能聚焦、选中、复制内容?
这直接影响可用性,尤其对需要复制订单号、API Key、调试 ID 的场景。
-
readonly允许:Tab切入、click聚焦、select()、Ctrl+A、Ctrl+C,也支持focus事件监听 -
disabled彻底阻断:Tab跳过、.focus()静默失败、无法选中或复制;CSS 的:focus或outline也无效 - 视觉上,
disabled默认变灰+低透明度;readonly外观无变化,需手动加:read-only { background: #eee; }或类似样式
哪些 HTML 元素支持 readonly?哪些只认 disabled?
不是所有表单控件都能用 readonly,强行写上等于白写。
立即学习“前端免费学习笔记(深入)”;
-
readonly仅对<input type="text">、<input type="password">、<input type="email">、<textarea>生效;对<select>、<input type="checkbox">、<button>完全无效,浏览器直接忽略 -
disabled通吃全部:<select>、<fieldset>、<button>都支持;<fieldset disabled>还能递归禁用内部所有子控件 - 想实现“只读下拉框”?别写
<select readonly>,要么换成<input type="text" readonly>模拟,要么 JS 禁用每个<option disabled>,或者改用纯文本展示
JS 动态控制时容易出错的点
脚本切换状态比静态写 HTML 更容易翻车,尤其跨浏览器兼容性。
- 设
disabled:直接写el.disabled = true或el.disabled = false,安全可靠 - 设
readonly:避免el.readOnly = false(某些旧版 Safari 不响应),稳妥做法是el.removeAttribute('readonly')启用,el.setAttribute('readonly', '')禁用 - 别同时写
readonly和disabled:disabled优先级更高,readonly形同虚设,还掩盖真实逻辑 - React/Vue 中注意属性名大小写:
readOnly(驼峰)才是 React 正确写法;Vue 的:readonly绑定到<select>上毫无作用
真正容易被忽略的是:某些 UI 库(比如 Ant Design 的 Input)把 readOnly 属性映射为原生 readonly,但文档没强调“它不影响提交”——开发在表单里写了 readOnly={true},测试阶段才发现后端少收了一个关键字段。



















