HTML属性(attribute)与DOM属性(property)是两套机制:getAttribute()获取HTML初始值,elem.xxx获取实时状态;表单控件应优先操作property,data-*属性是安全的双向桥梁。

HTML 属性和 JS 交互不冲突,但「属性(attribute)」和「属性(property)」在 DOM 中是两套不同机制,混用时容易出 bug —— 这才是实际问题的根源。
getAttribute() 和 elem.xxx 获取的不是同一个东西
HTML 中写的 disabled、value、checked 等,在 JS 里分“初始值”和“当前状态”两层:
-
getAttribute('disabled')拿的是 HTML 标签上写的原始字符串(比如返回""或"disabled"),DOM 删除该属性后就返回null -
elem.disabled是 JS 的 property,布尔类型,反映的是当前真实状态(哪怕没写disabled属性,JS 设为true后它就是true) -
value最典型:输入框手动改内容后,getAttribute('value')还是初始值,elem.value才是用户当前输入
修改表单控件状态,优先用 property 而非 setAttribute()
对 input、textarea、select、button 等,直接赋值 property 更可靠:
const input = document.querySelector('input');
input.value = '新内容'; // ✅ 正确更新显示和取值
input.checked = true; // ✅ 单选/复选框状态
input.disabled = false; // ✅ 控制禁用态
<p>// ❌ 避免这样:
input.setAttribute('value', '新内容'); // 只改 attribute,不更新 UI 实际值
input.setAttribute('disabled', ''); // 偶尔生效,但语义不清、兼容性差
</p>
例外:自定义属性(如 data-*)必须用 setAttribute() 或 dataset,因为它们没有对应 property。
监听变化时,attribute 和 property 的触发时机不同
用 MutationObserver 监听 attribute 变化,或用事件(如 input、change)监听用户交互,不能互相替代:
-
input.addEventListener('input', ...)响应用户输入,但不会响应elem.value = 'xxx'的 JS 修改 -
elem.setAttribute('value', 'xxx')会触发MutationObserver,但不会触发input事件,也不改变elem.value的当前值 - 想统一捕获所有 value 变更?得同时监听事件 + 主动轮询或劫持 setter(不推荐),通常按场景选一种即可
data-* 属性是安全的桥梁,但别滥用
当需要 JS 和 HTML 共享配置数据时,data- 是唯一被设计为双向同步的通道:
<button data-api-endpoint="/users" data-retry="3">提交</button>
JS 中可安全读写:
const btn = document.querySelector('button');
console.log(btn.dataset.apiEndpoint); // "/users"(自动转驼峰)
btn.dataset.retry = "5"; // ✅ 自动更新 attribute
注意:dataset 不支持数字、布尔等类型,全是字符串;且不要用它传大量状态(比如整个对象 JSON),那该用 JS 变量或 state 管理库。
最常踩的坑,是把 getAttribute('value') 当成实时值来用,或者用 setAttribute('checked') 来控制 checkbox 状态——这两处一错,表单逻辑就静默失效。记住:表单控件的状态,99% 场景下只认 property。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











