DOM操作

创建节点

使用DOM API创建新的节点。

createElement

// 创建元素节点
const div = document.createElement("div");
const span = document.createElement("span");
const img = document.createElement("img");

// 设置属性
div.id = "container";
div.className = "box active";
div.textContent = "东巴文";

// 创建SVG元素(需要指定命名空间)
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");

createTextNode

// 创建文本节点
const text = document.createTextNode("东巴文学习");

// 添加到元素
const p = document.createElement("p");
p.appendChild(text);

// 或使用textContent
const p2 = document.createElement("p");
p2.textContent = "东巴文学习";

createDocumentFragment

// 创建文档片段(轻量级容器)
const fragment = document.createDocumentFragment();

for (let i = 0; i < 5; i++) {
    const li = document.createElement("li");
    li.textContent = `项目${i + 1}`;
    fragment.appendChild(li);
}

// 一次性插入(减少重排)
const ul = document.querySelector("ul");
ul.appendChild(fragment);

createComment

// 创建注释节点
const comment = document.createComment("这是一个注释");
document.body.appendChild(comment);

插入节点

将节点插入到DOM树中。

appendChild

const parent = document.querySelector("#container");
const child = document.createElement("div");
child.textContent = "东巴文";

// 添加到末尾
parent.appendChild(child);

// 返回插入的节点
const result = parent.appendChild(child);
console.log(result === child);  // true

insertBefore

const parent = document.querySelector("ul");
const newItem = document.createElement("li");
newItem.textContent = "新项目";

const firstItem = parent.querySelector("li");

// 在firstItem之前插入
parent.insertBefore(newItem, firstItem);

// 插入到末尾(第二个参数为null)
parent.insertBefore(newItem, null);  // 等同于appendChild

append和prepend

const parent = document.querySelector("#container");

// append:在末尾添加多个节点
const div1 = document.createElement("div");
const div2 = document.createElement("div");
parent.append(div1, div2, "文本");

// prepend:在开头添加多个节点
parent.prepend("开头文本", div1);

// 支持字符串(自动转为文本节点)
parent.append("东巴文");

before和after

const element = document.querySelector("#target");

// before:在元素之前插入
const before = document.createElement("div");
element.before(before, "前面的文本");

// after:在元素之后插入
const after = document.createElement("div");
element.after(after, "后面的文本");

删除节点

从DOM树中移除节点。

removeChild

const parent = document.querySelector("ul");
const child = parent.querySelector("li");

// 从父元素中移除子元素
const removed = parent.removeChild(child);
console.log(removed);  // 被移除的节点

// 移除所有子元素
while (parent.firstChild) {
    parent.removeChild(parent.firstChild);
}

remove

const element = document.querySelector("#target");

// 直接移除元素
element.remove();

// 兼容性写法
if (element.remove) {
    element.remove();
} else {
    element.parentNode.removeChild(element);
}

清空元素

const element = document.querySelector("#container");

// 方法1:innerHTML
element.innerHTML = "";

// 方法2:textContent
element.textContent = "";

// 方法3:循环移除
while (element.firstChild) {
    element.removeChild(element.firstChild);
}

// 方法4:replaceChildren(现代方法)
element.replaceChildren();

替换节点

替换DOM中的节点。

replaceChild

const parent = document.querySelector("ul");
const oldChild = parent.querySelector("li");
const newChild = document.createElement("li");
newChild.textContent = "新项目";

// 用newChild替换oldChild
const replaced = parent.replaceChild(newChild, oldChild);
console.log(replaced);  // 被替换的节点

replaceWith

const element = document.querySelector("#target");
const newElement = document.createElement("div");
newElement.textContent = "新元素";

// 用新元素替换当前元素
element.replaceWith(newElement);

// 可以替换为多个节点
element.replaceWith("文本", newElement, document.createElement("span"));

replaceChildren

const parent = document.querySelector("#container");

// 替换所有子元素
parent.replaceChildren(
    document.createElement("div"),
    "文本内容",
    document.createElement("span")
);

// 清空(不传参数)
parent.replaceChildren();

克隆节点

复制DOM节点。

cloneNode

const original = document.querySelector("#original");

// 浅克隆:只克隆元素本身
const shallow = original.cloneNode();
console.log(shallow.childNodes.length);  // 0

// 深克隆:克隆元素及其所有后代
const deep = original.cloneNode(true);
console.log(deep.childNodes.length);  // 包含子节点

// 克隆后需要重新设置ID
deep.id = "cloned-" + Date.now();

克隆注意事项

const original = document.querySelector("#original");

// 1. 不会克隆事件监听器
original.addEventListener("click", () => console.log("点击"));
const clone = original.cloneNode(true);
// clone没有点击事件

// 2. ID会重复,需要修改
const clone2 = original.cloneNode(true);
clone2.id = "new-id";

// 3. 表单值不会被克隆
const input = document.querySelector("input");
input.value = "东巴文";
const inputClone = input.cloneNode();
console.log(inputClone.value);  // ""(空)

节点内容

获取和设置节点的内容。

innerHTML

const element = document.querySelector("#container");

// 获取HTML内容
console.log(element.innerHTML);

// 设置HTML内容
element.innerHTML = "<p>东巴文</p>";

// 安全风险:XSS攻击
// 不推荐直接插入用户输入
// element.innerHTML = userInput;  // 危险!

// 安全处理
function safeHTML(element, html) {
    element.textContent = html;  // 转义HTML
}

outerHTML

const element = document.querySelector("#target");

// 获取元素及其内容的HTML
console.log(element.outerHTML);  // "<div id='target'>内容</div>"

// 设置会替换整个元素
element.outerHTML = "<span>新内容</span>";
// 原元素被替换,element变量仍指向原元素

textContent

const element = document.querySelector("#container");

// 获取所有文本内容(包括隐藏元素)
console.log(element.textContent);

// 设置文本内容(自动转义HTML)
element.textContent = "<script>alert('xss')</script>";
// 显示为文本,不会执行脚本

innerText

const element = document.querySelector("#container");

// 获取可见文本(考虑CSS样式)
console.log(element.innerText);

// 设置文本
element.innerText = "东巴文";

// 与textContent的区别
// textContent:获取所有文本,包括隐藏元素
// innerText:只获取可见文本,触发重排

内容属性对比

属性 返回值 性能 安全 东巴文建议
innerHTML HTML字符串 需注意XSS 插入HTML
outerHTML 包含自身的HTML 需注意XSS 替换元素
textContent 纯文本 安全 获取/设置文本
innerText 可见文本 安全 获取可见文本

insertAdjacentHTML

在指定位置插入HTML。

语法

element.insertAdjacentHTML(position, text);

// position:
// "beforebegin" - 元素之前
// "afterbegin"  - 元素内部开头
// "beforeend"   - 元素内部末尾
// "afterend"    - 元素之后

使用示例

const element = document.querySelector("#target");

// 元素之前
element.insertAdjacentHTML("beforebegin", "<div>之前</div>");

// 元素内部开头
element.insertAdjacentHTML("afterbegin", "<div>开头</div>");

// 元素内部末尾
element.insertAdjacentHTML("beforeend", "<div>末尾</div>");

// 元素之后
element.insertAdjacentHTML("afterend", "<div>之后</div>");

相关方法

const element = document.querySelector("#target");

// insertAdjacentElement:插入元素
const div = document.createElement("div");
element.insertAdjacentElement("beforeend", div);

// insertAdjacentText:插入文本
element.insertAdjacentText("beforeend", "文本内容");

性能优势

// 使用innerHTML(会重新解析所有内容)
element.innerHTML += "<div>新内容</div>";

// 使用insertAdjacentHTML(只解析新内容)
element.insertAdjacentHTML("beforeend", "<div>新内容</div>");

// 后者性能更好

下一步

掌握了DOM操作后,让我们继续学习:

  1. DOM属性与样式 - 学习属性与样式
  2. 表单操作 - 学习表单操作
  3. 事件基础 - 学习事件处理

东巴文(db-w.cn) - 让编程学习更简单

🔨 东巴文寄语:DOM操作是前端开发的核心技能,掌握创建、插入、删除、替换节点的方法,能让你动态地改变页面内容。注意性能优化和安全性,写出高效的代码。在 db-w.cn,我们帮你精通DOM操作!