readonly仅对(text类)和有效,支持聚焦、复制且值可提交;对、、等无效;contenteditable元素须设contenteditable="false"而非readonly。

只读属性用 readonly,但仅对表单控件有效
readonly 是原生 HTML 属性,作用是让用户无法编辑内容,但元素仍可聚焦、可提交(值会随表单一起发送)。它只对 <input>(type="text、search、tel、url、email、number)、<textarea></textarea> 有效;对 <select></select>、<button></button>、普通 <div> 等无效。
<p>常见错误是给 <code><div> 或 <code><span></span> 加 readonly——浏览器完全忽略,既不阻止输入(因为本来就不能输入),也不改变样式或行为。
- 正确用法:
<input type="text" readonly value="不可改"> - JS 动态设置:
el.setAttribute('readonly', 'readonly')或el.readOnly = true(注意大小写:JS 中是readOnly) - 与
disabled的关键区别:readonly元素仍参与表单提交,disabled则不会
contenteditable 元素怎么设只读?不能用 readonly
如果用了 contenteditable="true" 的 <div> 或 <code><p></p>,readonly 属性不起作用。必须显式关闭编辑能力:
- 设为
contenteditable="false"(最直接) - 或用 CSS 阻断用户交互:
pointer-events: none+user-select: none(但只是视觉/交互屏蔽,不能防 JS 修改) - 更稳妥的做法是监听
beforeinput或keydown并event.preventDefault(),同时确保tabindex="-1"避免键盘聚焦
注意:contenteditable="plaintext-only" 不是标准属性,不要依赖。
用 disabled 替代 readonly 的陷阱
disabled 看似也能禁用编辑,但它会带来副作用:表单提交时该字段的值被忽略、默认变灰、失去焦点能力、屏幕阅读器可能跳过。所以别为了“看起来只读”就滥用 disabled。
- 需要提交值 → 必须用
readonly(仅限支持的表单控件) - 不需要提交值,且想彻底禁用交互 → 用
disabled - 自定义组件(如封装的日期选择器)内部若含
<input>,应把readonly透传到原生<input>上,而不是只加在容器上
CSS 和 JS 配合才能覆盖所有只读场景
纯 HTML 属性解决不了全部问题。比如要让一个 <input type="date"> 只读但保留日期图标(readonly 会隐藏 Chrome 的下拉箭头),就得用 CSS 隐藏原生控件 + 自定义展示,再用 JS 拦截所有修改路径。
- 阻止粘贴:
onpaste="return false"或监听paste事件 - 防止通过开发者工具修改:
Object.defineProperty(input, 'value', { writable: false })(仅运行时防护,不替代语义属性) - 无障碍考虑:只读状态需通过
aria-readonly="true"显式声明,尤其对非标准控件
真正难的不是加个属性,而是判断这个“只读”到底要阻断哪些行为、在哪些上下文中生效、是否影响数据流和可访问性——这些得根据具体组件边界来定。











