
2.2 DOM 元素内容与属性操作元素内容与属性操作是 DOM 视图动态更新的核心手段通过 JavaScript 可以实时修改页面的文本内容、HTML 结构与标签属性实现数据渲染、状态切换、交互反馈等核心交互效果。不同的内容操作方式在安全性、性能、语义上存在显著差异理解其边界与适用场景是规避 XSS 风险、性能损耗与兼容性问题的基础。2.2.1 内容读写操作innerHTML/innerText/textContentJavaScript 提供了三种常用的元素内容读写属性分别面向 HTML 结构、可见文本、全量文本三种场景三者在读取范围、写入行为、安全性能上差异明显。一、innerHTMLinnerHTML用于读写元素内部的完整 HTML 代码。读取时返回元素内所有 HTML 标记字符串写入时会将字符串作为 HTML 解析生成新的 DOM 节点替换原有内容。const box document.querySelector(.box); // 读取 HTML 结构 console.log(box.innerHTML); // 写入 HTML 结构浏览器会自动解析标签生成 DOM box.innerHTML p这是一段strong加粗/strong文本/p;核心特点支持渲染完整 HTML 结构是富文本、模板渲染的核心方式写入时会销毁原有子节点及其事件绑定完整重建 DOM 子树高安全风险直接插入未过滤的用户输入会导致 XSS 攻击性能开销大大量 HTML 写入会触发完整的解析、重排与重绘二、innerTextinnerText用于读写元素的可见文本内容返回结果与用户肉眼在页面上看到的文本一致受 CSS 样式影响。const box document.querySelector(.box); console.log(box.innerText); // 仅返回页面可见的文本 box.innerText p纯文本/p; // 会作为纯文本显示不会解析标签核心特点写入时作为纯文本处理不会解析 HTML 标签天然防御 XSS读取时会触发 CSS 样式计算重排性能较差自动忽略display: none的隐藏元素、script/style内的文本会保留换行与基本排版格式输出更贴近视觉效果三、textContenttextContent用于读写元素内的全部文本内容包含所有子节点的文本不考虑 CSS 样式与元素可见性。const box document.querySelector(.box); console.log(box.textContent); // 返回所有文本包括隐藏元素的内容 box.textContent 纯文本内容; // 纯文本写入不解析标签核心特点写入时纯文本处理无 XSS 安全风险读取时不触发样式计算性能远优于innerText会获取所有文本节点包括隐藏元素、注释外的所有文本内容不会自动处理排版格式仅保留原始文本的换行符四、三者对比与选型对比维度innerHTMLinnerTexttextContent读取内容完整 HTML 代码包含标签仅可见文本受 CSS 影响全部文本内容含隐藏文本写入行为解析 HTML 标签重建 DOM纯文本渲染不解析标签纯文本渲染不解析标签安全性存在 XSS 注入风险安全无 XSS 风险安全无 XSS 风险性能表现差触发完整解析与重排较差读取触发样式重排好仅操作文本节点适用场景可信 HTML 结构渲染需要匹配视觉可见文本的场景纯文本读写、性能优先场景五、最佳实践纯文本更新优先使用textContent性能最优且安全仅在渲染可信 HTML 内容时使用innerHTML用户输入内容必须先做 XSS 过滤避免频繁调用innerHTML做小幅修改优先操作具体节点的属性与文本大量内容渲染避免字符串拼接式innerHTML推荐使用DocumentFragment批量操作2.2.2 原生属性与自定义属性操作HTML 元素的属性分为原生标准属性如id、class、src和自定义属性两类JavaScript 提供了两套操作方式DOM 对象属性直接访问、Attribute 系列方法二者在行为上存在关键差异。一、DOM 对象属性直接访问点语法通过element.属性名直接读写 DOM 对象的属性仅支持原生标准属性操作的是内存中 DOM 对象的属性值而非 HTML 标签上的原始值。const input document.querySelector(input); // 读取原生属性 console.log(input.id); console.log(input.value); // 修改原生属性 input.className active; input.disabled true;核心特点仅支持标准原生属性无法直接操作非标准自定义属性返回值是经过浏览器处理的当前状态值而非标签原始字符串例如img.src返回完整绝对路径而非标签上的相对路径布尔属性disabled、checked返回真正的布尔值true/false直接操作内存对象读写性能更高二、Attribute 系列方法通过getAttribute()、setAttribute()、removeAttribute()、hasAttribute()方法操作 HTML 标签上的属性支持所有属性包括自定义属性操作的是标签上的原始字符串值。const link document.querySelector(a); // 获取属性值返回标签上的原始值 console.log(link.getAttribute(href)); // 返回相对路径字符串 // 设置属性 link.setAttribute(target, _blank); // 判断属性是否存在 console.log(link.hasAttribute(title)); // 删除属性 link.removeAttribute(custom-attr);核心特点支持所有属性包括非标准自定义属性返回值始终是字符串或null布尔属性返回属性名本身或null操作会直接修改 HTML 标签结构变化可反映在outerHTML中性能略低于 DOM 对象直接属性访问三、核心差异对比对比项DOM对象属性点语法Attribute系列方法支持范围仅原生标准属性所有属性含自定义属性返回值类型对应属性的实际类型布尔、数字等始终为字符串 /null值内容浏览器计算后的当前值如绝对路径标签上的原始字符串值布尔属性返回 true /false 布尔值返回属性名 /null读写性能高直接操作内存略低操作标签结构四、常见坑点class 属性特殊处理DOM 对象中对应className而非class因为class是 JavaScript 保留字。布尔属性赋值setAttribute(disabled, false)依然会生效因为布尔属性只要存在即为真移除需用removeAttribute()。value 属性差异input.value是用户输入的实时值getAttribute(value)是标签上的初始默认值。2.2.3>data-*是 HTML5 标准化的自定义属性方案通过统一的data-前缀定义自定义属性既符合标准规范又避免与未来原生属性冲突同时配套了专属的datasetAPI是元素关联业务数据的推荐方式。一、基础语法与命名规则在 HTML 标签中以data-为前缀后面跟自定义属性名多单词命名使用横杠分隔DOM 中对应dataset属性是一个DOMStringMap对象自动将横杠命名转换为驼峰命名示例!-- HTML 中定义>二、核心特点标准合规W3C 官方标准方案不会与原生属性冲突兼容所有现代浏览器双向同步修改dataset会同步更新 HTML 标签属性修改标签属性也会同步到 dataset字符串限制所有值都会被转为字符串存储数字、布尔值等读取后需要手动转换类型语义化明确标识为自定义数据属性提升 HTML 源码可读性三、典型应用场景列表项数据绑定给列表元素绑定业务 ID、状态等数据事件委托中直接读取const list document.querySelector(.list); list.addEventListener(click, (e) { const item e.target.closest(li); if (item) { const id item.dataset.id; console.log(点击了项, id); } });状态标记标记元素的交互状态如展开 / 收起、加载中配合 CSS 属性选择器控制样式配置传递在 DOM 标签上预置组件配置参数组件初始化时统一读取四、注意事项仅适合存储少量简单数据大量复杂数据建议使用Map与元素关联存储所有值均为字符串类型读取后需根据业务做显式类型转换避免存储敏感信息data-*属性会直接暴露在 HTML 源码中严格遵循横杠转驼峰命名规则不要在 dataset 中使用大写字母直接命名