readonly仅对<input>(text、search、tel、url、email、number)和<textarea>生效,对<select>、<button>、<div>等无效;需提交值时用readonly,不提交且彻底禁用交互时用disabled。

只读或禁用编辑,不能靠一个属性通吃所有元素——readonly 和 disabled 各有明确适用范围,乱用会导致值丢、交互异常、无障碍失效。
哪些元素支持 readonly?
readonly 只对 <input>(type 为 text、search、tel、url、email、number)和 <textarea> 生效;对 <select>、<button>、<div>、<p> 等完全无效,浏览器会静默忽略。
- 给
<input type="date">加readonly,Chrome 会隐藏原生下拉箭头,但值仍可提交 - JS 动态设置时注意大小写:
el.readOnly = true(不是readonly),否则不生效 - 若需保留样式(如不让背景变灰),必须配合 CSS:
input[readonly] { background: #fff; }
contenteditable 元素怎么设只读?
readonly 对 contenteditable="true" 的 <div> 或 <p> 不起作用。唯一语义正确的方式是显式关闭编辑能力:
- 设
contenteditable="false"(推荐,直接切断编辑引擎接管) - 避免仅靠
pointer-events: none+user-select: none—— 它们拦不住Tab聚焦、键盘输入或粘贴 - Firefox 下
contenteditable="false"子元素仍可能被 Backspace 合并删除,建议加data-locked="true"并监听beforeinput做e.preventDefault() - 必须同步设置
aria-readonly="true",否则屏幕阅读器无法感知只读状态
disabled 和 readonly 到底选哪个?
核心区别就一条:是否要让值随表单提交。
立即学习“前端免费学习笔记(深入)”;
- 需要提交值 → 必须用
readonly(仅限支持的表单控件) - 不需要提交值,且想彻底禁用交互(包括聚焦、选中、复制)→ 用
disabled -
disabled会让<input type="hidden">失效,且所有浏览器默认置灰、跳过键盘导航、被屏幕阅读器标记为“不可用” - 别为了“看起来像只读”而滥用
disabled—— 比如展示订单号却不想用户改,又要求后端收到这个值,这时disabled就直接丢数据
自定义组件里怎么透传只读状态?
封装的日期选择器、富文本编辑器等,内部若含原生 <input>,必须把只读逻辑透传到底层控件,而不是只加在容器上:
- 容器加
data-readonly="true"是标记,不是行为 - 真正起作用的是:找到内部
<input>,设el.readOnly = true或el.setAttribute('readonly', 'readonly') - 如果组件允许用户通过弹层修改值,还需拦截
keydown、paste、beforeinput,否则只靠属性形同虚设 - 移动端尤其要注意:Safari 对
contenteditable行为不一致,readonly在部分 iOS 输入法下仍可能被绕过,需 JS 双重防护
真正难的不是加个属性,而是判断这个字段在业务流里“该不该交出去”。值要不要进后端、光标能不能停在这儿、屏幕阅读器该怎么念、开发者工具改了有没有影响——这些才是决定用哪个属性、加不加 JS、配不配 ARIA 的依据。



















