前言
DOM节点操作是JavaScript动态操作网页的核心技术。本文系统讲解节点的创建与添加 、替换与删除 、克隆复制 以及多种创建方式的对比,最后给出性能优化的建议。掌握这些内容,你就能轻松实现页面的动态内容管理。
一、创建和添加节点
1.1 创建节点
创建元素节点
document.createElement('标签名');
- 参数:标签名字符串(如
'div'、'li'、'span') - 返回值:新创建的元素节点对象
- 这些元素原先不存在,是根据需求动态生成的
创建文本节点
document.createTextNode('文本内容');
- 参数:文本内容字符串
- 返回值:新创建的文本节点对象
1.2 添加节点
appendChild() --- 末尾追加
将一个节点添加到指定父节点的子节点列表的末尾,类似于数组的 push() 方法,也类似于CSS中的 ::after 伪元素。
father.appendChild(child);
insertBefore() --- 指定位置插入
将一个节点添加到父节点的指定子节点前面,类似于CSS中的 ::before 伪元素。
father.insertBefore(newNode, referenceNode);
1.3 完整示例
let box = document.querySelector(".box");
let p = document.querySelector("p");
let btns = document.querySelectorAll("button");
// 需求1:在段落p后面追加span标签
btns[0].onclick = function() {
// 1.1 创建span元素节点
let spanEle = document.createElement("span");
// 1.2 创建文本节点
let spanText = document.createTextNode("我是一个span");
// 1.3 将文本节点添加到span元素中
spanEle.appendChild(spanText);
// 1.4 将span元素追加到父容器末尾
box.appendChild(spanEle);
};
// 需求2:在段落p前面添加h1标签
btns[1].onclick = function() {
// 2.1 创建h1元素节点
let h1Ele = document.createElement("h1");
// 2.2 创建文本节点
let h1Text = document.createTextNode("我是一个h1");
// 2.3 将文本放入h1节点
h1Ele.appendChild(h1Text);
// 2.4 在p标签前插入h1
box.insertBefore(h1Ele, p);
};
1.4 方法速查
| 方法 | 功能 | 类比 |
|---|---|---|
appendChild(child) |
在父元素末尾追加子节点 | 数组的push() |
insertBefore(new, ref) |
在指定子节点前插入新节点 | CSS的::before |
二、替换和删除节点
2.1 替换节点 --- replaceChild()
使用指定的子节点替换已有的子节点。
父节点.replaceChild(新节点, 旧节点);
let ul = document.querySelector("ul");
let jpm = document.getElementById("jpm"); // 要替换的旧节点
btns[0].onclick = function() {
// 创建新的li元素
let liEle = document.createElement("li");
let liText = document.createTextNode("《水浒传》");
liEle.appendChild(liText);
// 替换节点:用新节点替换指定节点
ul.replaceChild(liEle, jpm);
};
2.2 删除节点 --- removeChild()
从DOM中删除一个子节点,返回被删除的节点。
两种写法:
// 写法一:通过父元素删除
father.removeChild(child);
// 写法二:通过节点自身的parentNode属性删除
child.parentNode.removeChild(child);
btns[1].onclick = function() {
// 方法一:直接通过父元素删除
ul.removeChild(jpm);
// 方法二:通过节点的parentNode属性删除
jpm.parentNode.removeChild(jpm);
};
2.3 方法速查
| 方法 | 功能 | 返回值 |
|---|---|---|
replaceChild(new, old) |
用新节点替换旧节点 | 被替换的旧节点 |
removeChild(child) |
删除指定子节点 | 被删除的节点 |
三、克隆节点
3.1 cloneNode() 方法
返回调用该方法的节点的一个副本。
node.cloneNode(deep);
参数说明:
| 参数值 | 含义 | 说明 |
|---|---|---|
false(默认) |
浅拷贝 | 只克隆节点本身,不克隆子节点 |
true |
深拷贝 | 克隆节点及其所有子节点 |
3.2 完整示例
document.querySelector("button").onclick = function() {
let box = document.querySelector(".box");
// 浅拷贝:只拷贝节点本身(不包含子元素)
let boxCloneShallow = box.cloneNode(); // 默认false
// 深拷贝:拷贝节点及所有子节点
let boxCloneDeep = box.cloneNode(true);
// 将克隆的节点添加到DOM中
box.parentNode.appendChild(boxCloneDeep);
};
3.3 深浅拷贝对比
| 拷贝方式 | 参数 | 克隆内容 | 应用场景 |
|---|---|---|---|
| 浅拷贝 | false |
仅节点外壳 | 需要空容器模板时 |
| 深拷贝 | true |
节点及所有后代 | 复制完整的组件结构 |
四、创建节点的其他方式
4.1 innerHTML
允许更改HTML元素的内容,可以设置或返回元素开始和结束标签之间的HTML,可以解析HTML标签。
// 获取HTML内容(包含标签)
let test1 = ul.innerHTML;
// 设置HTML内容(会解析标签)
ul.innerHTML = "<li>《红楼梦》</li><li>《水浒传》</li>";
4.2 innerText
获取或设置元素的文本------以纯文本的方式直接显示,不可以解析HTML标签。
// 获取文本内容(不包含标签)
let test2 = ul.innerText;
// 设置文本内容(不会解析标签,直接显示为文本)
ul.innerText = "<li>《红楼梦》</li>"; // 页面显示为文本字符串
4.3 document.write()
直接将内容写入页面的内容流,但文档执行完毕后使用会导致页面全部重绘。
document.write("<h2>新内容</h2>");
警告 :如果在页面加载完成后调用 document.write(),它会覆盖整个页面内容,慎用!
4.4 insertAdjacentHTML() --- 灵活插入
insertAdjacentHTML() 可以将字符串文本转化为节点,并插入到指定位置。它不会像 innerHTML 那样替换已有节点,而是插入到指定位置。
element.insertAdjacentHTML(position, text);
position参数:
| 参数值 | 插入位置 | 示意图 |
|---|---|---|
beforebegin |
元素本身的前面(作为前一个兄弟节点) | ←新·元素→ |
afterbegin |
元素内部的开头(作为第一个子节点) | 元素内↑ |
beforeend |
元素内部的末尾(作为最后一个子节点) | 元素内↓ |
afterend |
元素本身的后面(作为后一个兄弟节点) | 元素·新→ |
let str = "<li>《水浒传》</li>";
// 在ul内部开头插入
ul.insertAdjacentHTML("afterbegin", str);
// 在ul内部末尾插入
ul.insertAdjacentHTML("beforeend", str);
// 在ul前面插入(作为前一个兄弟)
ul.insertAdjacentHTML("beforebegin", str);
// 在ul后面插入(作为后一个兄弟)
ul.insertAdjacentHTML("afterend", str);
4.5 创建方式对比
| 方式 | 是否解析HTML | 是否替换现有内容 | 性能 |
|---|---|---|---|
createElement |
✅ 需手动添加 | ❌ 不替换 | 较好 |
innerHTML |
✅ 解析 | ✅ 会替换 | 一般 |
innerText |
❌ 不解析 | ✅ 会替换 | 一般 |
document.write() |
✅ 解析 | ✅ 可能重绘 | 差 |
insertAdjacentHTML |
✅ 解析 | ❌ 不替换 | 较好 |
五、性能优化与最佳实践
5.1 核心方法汇总
| 操作 | 方法 | 说明 |
|---|---|---|
| 创建节点 | createElement() |
创建元素节点 |
createTextNode() |
创建文本节点 | |
| 添加节点 | appendChild() |
末尾追加 |
insertBefore() |
指定位置插入 | |
| 替换节点 | replaceChild() |
替换子节点 |
| 删除节点 | removeChild() |
删除子节点 |
| 克隆节点 | cloneNode() |
复制节点(深浅拷贝) |
5.2 性能优化建议
| 场景 | 建议 | 原因 |
|---|---|---|
| 大量DOM操作 | 使用 DocumentFragment |
减少回流和重绘次数 |
| 批量添加 | 拼接HTML后用 innerHTML 一次性插入 |
减少DOM操作次数 |
| 灵活插入 | 使用 insertAdjacentHTML |
不替换现有内容,性能更好 |
| 避免频繁操作 | 合并多次修改为一次操作 | 减少浏览器渲染压力 |
5.3 实际应用场景
| 场景 | 推荐方案 |
|---|---|
| 动态加载列表内容 | createElement + appendChild |
| 模板渲染 | innerHTML 或 insertAdjacentHTML |
| 列表项增删改查 | removeChild + replaceChild |
| 动态表单生成 | createElement 逐项构建 |
| 复制组件结构 | cloneNode(true) 深拷贝 |
总结
本文系统梳理了JavaScript DOM节点操作的完整知识体系:
| 主题 | 核心要点 |
|---|---|
| 创建节点 | createElement() 创建元素,createTextNode() 创建文本 |
| 添加节点 | appendChild() 末尾追加,insertBefore() 指定位置插入 |
| 替换删除 | replaceChild() 替换,removeChild() 删除 |
| 克隆节点 | cloneNode(false) 浅拷贝,cloneNode(true) 深拷贝 |
| 其他方式 | innerHTML、innerText、insertAdjacentHTML 各有优劣 |
| 性能优化 | DocumentFragment、批量操作、合理选择创建方式 |
掌握这些内容,你就能灵活地通过JavaScript动态操控网页内容。