优先用 getElementById(性能好、语义清),无 id 时用 querySelector;textContent 仅设纯文本并自动转义,innerHTML 解析 HTML 但有 XSS 风险;批量操作用 DocumentFragment 减少重排;动态元素绑定事件应即时或用事件委托。

用 getElementById 或 querySelector 获取元素再改内容
想改网页某块文字或 HTML,第一步永远是“找到它”。getElementById 最快最稳,前提是目标有 id;没 id 就用 querySelector,支持类名、标签、属性选择器,比如 querySelector('.title') 或 querySelector('button[data-action="save"]')。
常见错误:选错选择器导致返回 null,后续调用 innerHTML 或 textContent 直接报 Cannot set property 'innerHTML' of null。建议先 console.log 一下获取结果,确认不为空再操作。
实操建议:
- 优先用
getElementById(性能好、语义清) - 动态生成的元素,确保 JS 执行时机晚于 DOM 加载(放在
</body>前,或用DOMContentLoaded) - 避免用
document.write——它会覆盖整个页面,且只在页面加载中有效
textContent 和 innerHTML 的区别必须分清
textContent 只改纯文本,自动转义 HTML 字符(比如把 <strong>Hi</strong> 当作普通字符串显示);innerHTML 解析并渲染 HTML,但有 XSS 风险——如果内容来自用户输入,直接塞进去可能执行恶意脚本。
立即学习“Java免费学习笔记(深入)”;
使用场景:
- 显示用户昵称、评论、表单提示文字 → 用
textContent - 插入带格式的富文本(如后台返回的带
<p>、<span>的内容)→ 用innerHTML,但务必先过滤或使用DOMPurify等库净化 - 想清空一个容器所有子节点 →
element.innerHTML = ''比循环removeChild更简洁(现代浏览器下性能也够用)
批量更新用 DocumentFragment 减少重排重绘
一次性往列表里加 100 个 <li>?如果用循环 + appendChild,每加一个都可能触发浏览器重排(reflow),卡顿明显。这时候该上 DocumentFragment。
它是个轻量级的“离屏容器”,所有操作都在内存里完成,最后一次性挂到真实 DOM 上:
const frag = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
frag.appendChild(li);
}
document.getElementById('myList').appendChild(frag);
注意点:
-
DocumentFragment不是真实 DOM 节点,不能用querySelector查找它内部元素(得先 append 到文档后才能查) - 现代框架(React/Vue)已内置类似优化,手写 DOM 操作时才需手动考虑
- 小批量操作(如增删 1–5 个节点)没必要上 fragment,代码反而冗余
监听动态内容变化:别依赖 innerHTML 改变后的 DOM 快照
很多人以为改完 innerHTML,再立刻用 querySelector 去找新插入的按钮就能绑定事件——结果找不到。因为 JS 是同步执行的,但 DOM 更新虽快,事件绑定逻辑若写在后面,有时会因执行顺序或异步渲染(如某些 UI 库的 lazy mount)而失效。
更可靠的做法:
- 新元素创建后立即绑定事件,而不是等它“出现在页面上”再找
- 用事件委托:给父容器绑事件,利用事件冒泡捕获子元素触发,比如
list.addEventListener('click', e => { if (e.target.matches('button.delete')) { ... } }) - 避免反复查询同一元素,缓存引用(如
const btn = document.querySelector('#saveBtn')),否则每次调用都触发查找开销
真正容易被忽略的是:DOM 操作本身不保证视觉立即刷新。如果连续修改多个样式或内容,浏览器可能合并渲染,想强制重绘得用 offsetHeight 或 getComputedStyle 触发回流——但绝大多数场景不需要,强行触发反而伤性能。











