真正影响运行时行为的全局属性仅有 id、class、data-*、tabindex、hidden、contenteditable 等少数几个;用错会导致 JS 选不到、CSS 不生效或无障碍失效,因其行为由存在性、命名规范及值合法性共同决定,而非简单添加即可生效。

真正影响运行时行为的全局属性只有几个,其余多数是“语法合法但无实际效果”。用错 id、class、data-*、tabindex、hidden 或 contenteditable,JS 就选不到、CSS 不生效、无障碍直接失效。
为什么 id 和 class 最容易翻车
它们看似最基础,却是动态渲染和调试中出问题频率最高的两个:
- 多个元素用了相同
id:JS 的document.getElementById()只返回第一个,后续逻辑全崩;CSS 选择器仍会命中全部,导致样式覆盖混乱 -
class值含空格却没加引号:<div class="btn" primary></div>实际只生效btn,primary被当作文本节点丢弃 - 动态拼接
class时没去重:el.className += " active"多次执行后变成active active active,CSS 仍生效,但classList.contains("active")会返回false - 服务端模板中未转义
class名:class="{{ user.role }}"若user.role是"admin script",可能意外引入非法 class 并触发 XSS
data-* 属性不是“随便塞字符串”的地方
它有明确的读写边界和隐式转换规则,不是所有写法都能在 JS 中拿到:
- 连字符自动转驼峰:
data-user-id="123"→ JS 中必须用dataset.userId访问,dataset.user-id是语法错误 - 数字开头的 key 被忽略:
data-1st-place="gold"在dataset中完全不可见 - IE11 支持
dataset,但不支持大写字母转换:data-MyKey→mykey(不是myKey) - 不要存对象或函数:它只序列化为字符串,存前得
JSON.stringify(),取回得自己JSON.parse() - Vue/React 中改了 DOM 上的
data-*,组件状态不会响应式更新
hidden、contenteditable、tabindex 是布尔/枚举属性,值不是“开关”
它们的行为由是否存在、是否符合规范决定,而不是靠字符串值“控制”:
立即学习“前端免费学习笔记(深入)”;
-
hidden是布尔属性:写成hidden="false"或hidden="0"依然隐藏;只要存在就生效,值无效 -
contenteditable只接受"true"或"false"字符串(注意是字符串);contenteditable="0"、contenteditable="off"全部无效 -
tabindex值为0或正整数才参与 Tab 焦点流;负值(如-1)仅禁用焦点,不改变顺序;tabindex="null"或tabindex=""会被忽略,等效于未设置
title、lang、aria-* 这类“隐形属性”不显眼,但缺了就出事
它们不改样式、不触发行内逻辑,但缺失会导致具体可测的问题:
-
title:鼠标悬停提示,但不保证一定出现——移动端 Safari 完全不支持,部分屏幕阅读器默认忽略 -
lang缺失:影响语音合成器发音、搜索引擎语种识别、拼写检查准确性 -
aria-labelledby等 ARIA 属性依赖id关联,若目标id不存在或重复,无障碍树直接断裂 -
dir错用(比如该rtl却写ltr):阿拉伯/希伯来文字显示错乱,文本光标跳转异常
全局属性不是装饰品,而是运行时行为的控制开关。最容易被忽略的是它们的“存在即生效”特性,以及 JS/CSS/无障碍三者对同一属性的不同解析逻辑——同一个 hidden,浏览器渲染、JS 判断、屏幕阅读器播报,各自有一套规则。



















