JavaScript: DOM 操作
DOM(文档对象模型)是浏览器把 HTML 文档翻译成的一棵"树"。你通过 JavaScript 操作这棵树,就能动态改变页面的内容、结构和属性——就像在树上摘果子、嫁接新枝、砍掉枯枝。
1. 选择元素
操作 DOM 的第一步永远是"先找到它"。
| 方法 | 返回 | 说明 |
|---|---|---|
getElementById('id') |
单个元素 | 最快,id 唯一 |
getElementsByClassName('cls') |
HTMLCollection | 动态集合,元素增减会同步 |
getElementsByTagName('tag') |
HTMLCollection | 同上 |
querySelector('selector') |
单个元素 | CSS 选择器,返回第一个匹配 |
querySelectorAll('selector') |
NodeList | 静态集合,不会随 DOM 变化 |
💡 提示:
querySelector 系列 vs getElementBy*:前者用 CSS 选择器更灵活,后者性能略优。日常开发优先用 querySelector,够直观。
▶ 示例
JAVASCRIPT
// 本节代码示例
const message = "你好,世界!";
console.log(message);
这是最简单的示例,后续章节会详细解释。### ▶ 示例:五种选择方法对比
HTML
<div id="box" class="card active">Hello</div>
<div class="card">World</div>
<p class="card">JS</p>
<script>
const byId = document.getElementById('box');
console.log('byId:', byId.textContent);
const byClass = document.getElementsByClassName('card');
console.log('byClass 数量:', byClass.length);
const byTag = document.getElementsByTagName('p');
console.log('byTag:', byTag[0].textContent);
const first = document.querySelector('.card');
console.log('querySelector:', first.textContent);
const all = document.querySelectorAll('.card');
console.log('querySelectorAll 数量:', all.length);
</script>
2. 修改内容
找到元素后,最常见的需求就是改它"写了什么"。
textContent:读写纯文本,安全高效。innerHTML:读写 HTML 字符串,能插入标签,但有 XSS 风险。
⚠️ 注意: 永远不要用
innerHTML 插入用户输入的内容,否则攻击者可以注入恶意脚本。这就像把陌生人写的信直接贴到公告栏——信里可能藏着"炸弹"。
▶ 示例:textContent vs innerHTML
HTML
<div id="safe"></div>
<div id="danger"></div>
<script>
const safe = document.getElementById('safe');
safe.textContent = '<b>这段不会被加粗</b>';
const danger = document.getElementById('danger');
danger.innerHTML = '<b>这段会被加粗</b>';
</script>
3. 修改属性
HTML 元素的属性(id、class、src、href 等)也可以用 JS 读写。
| 方法 | 说明 |
|---|---|
getAttribute('name') |
读取属性值 |
setAttribute('name', 'value') |
设置属性 |
removeAttribute('name') |
删除属性 |
💡 提示: 有些属性可以直接用点号访问:
el.id、el.className、el.src。但自定义属性(data-*)推荐用 getAttribute 或 el.dataset。
▶ 示例:操作链接属性
HTML
<a id="link" href="https://example.com" target="_blank">示例链接</a>
<script>
const link = document.getElementById('link');
console.log('href:', link.getAttribute('href'));
link.setAttribute('href', 'https://mdn.io');
link.setAttribute('title', '点击去 MDN');
link.removeAttribute('target');
console.log('修改后:', link.getAttribute('href'));
</script>
4. 创建与插入元素
DOM 操作的核心能力之一:凭空"捏"出一个元素,然后挂到树上去。
| 方法 | 说明 |
|---|---|
createElement('tag') |
创建元素节点 |
createTextNode('text') |
创建文本节点 |
appendChild(child) |
追加到末尾 |
insertBefore(new, ref) |
在 ref 前插入 |
▶ 示例:动态添加列表项
HTML
<ul id="list">
<li>已有项目</li>
</ul>
<script>
const list = document.getElementById('list');
const li = document.createElement('li');
li.textContent = '新添加的项目';
list.appendChild(li);
const li2 = document.createElement('li');
li2.textContent = '插入到最前面';
list.insertBefore(li2, list.firstChild);
</script>
5. 删除与克隆元素
| 方法 | 说明 |
|---|---|
removeChild(child) |
父节点删除子节点 |
remove() |
元素删除自己(较新 API) |
cloneNode(true/false) |
true 深克隆(含子节点),false 浅克隆 |
💡 提示:
remove() 比 removeChild() 更简洁,但如果你需要拿到被删除的节点做后续处理,就用 removeChild(),它会返回被删除的节点。
▶ 示例:删除与克隆
HTML
<ul id="fruits">
<li>苹果</li>
<li>香蕉</li>
<li>橘子</li>
</ul>
<script>
const fruits = document.getElementById('fruits');
const banana = fruits.children[1];
const removed = fruits.removeChild(banana);
console.log('删除了:', removed.textContent);
const clone = fruits.cloneNode(true);
document.body.appendChild(clone);
console.log('克隆了一份列表');
</script>
❓ 常见问题
Q
querySelector 返回 null 会怎样?A 对
null 调用任何属性/方法都会报 TypeError。所以操作前最好判断:const el = document.querySelector('.xxx'); if (el) { ... }。Q
HTMLCollection 和 NodeList 有什么区别?A
HTMLCollection 是动态的——DOM 变了它自动变;querySelectorAll 返回的 NodeList 是静态快照。遍历时如果会增删元素,用静态集合更安全,否则可能死循环。Q
appendChild 已存在的节点会怎样?A 节点会从原位置"搬家"到新位置,DOM 中同一个节点只能出现一次。这不是复制,是移动。
📖 小节
- 选择元素有两大阵营:
getElementBy*(性能优)和querySelector*(灵活优),日常用querySelector即可 - 改文本用
textContent,改 HTML 才用innerHTML,后者务必防范 XSS - 属性操作三板斧:
getAttribute读、setAttribute写、removeAttribute删 - 创建元素的标准流程:
createElement→ 设置内容/属性 →appendChild挂载 - 删除元素两种方式:
remove()自己走,removeChild()父亲赶(还能拿回节点) cloneNode(true)深克隆包含所有后代,cloneNode(false)只克隆壳
📝 作业
- 基础:创建一个页面,用
createElement和appendChild动态生成一个包含 5 个城市名的列表。 - 进阶:给上题的列表添加一个删除按钮,点击后用
removeChild删除对应的列表项。 - 挑战:实现一个简单的"笔记管理器"——输入框 + 添加按钮,每次添加创建一个带删除按钮的卡片,点击删除按钮移除该卡片。