DOM 元素增删改

创建新元素、插入到页面、删除不需要的元素——这些操作让页面能动态响应数据变化,而无须刷新页面。

创建元素

createElement() — 创建元素节点

javascript
const div = document.createElement('div');
div.textContent = '我是动态创建的';
div.className = 'box';
div.id = 'dynamic-1';
document.write(div.outerHTML);
html
<div id="output"></div>

此时元素只存在于内存中,还没有出现在页面上——需要显式插入。

createTextNode() — 创建文本节点

javascript
const textNode = document.createTextNode('文本内容');
// 通常直接用 textContent 更简单

插入节点

appendChild() — 追加到末尾

javascript
const newItem = document.createElement('li');
newItem.textContent = '新项目';

const list = document.querySelector('ul');
list.appendChild(newItem);
html
<ul><li>项目1</li><li>项目2</li></ul>

insertBefore() — 插入到指定位置之前

javascript
const list = document.querySelector('ul');
const firstItem = list.querySelector('li');

const newItem = document.createElement('li');
newItem.textContent = '插入到第一个';
list.insertBefore(newItem, firstItem);
html
<ul><li>原有项目</li><li>项目2</li><li>项目3</li></ul>

append() / prepend() — 现代方法(推荐)

javascript
function makeItem(text) {
  const li = document.createElement('li');
  li.textContent = text;
  return li;
}

const list = document.querySelector('ul');

list.append('纯文本也可以', makeItem('新项目'));
list.prepend(makeItem('第一个'));
html
<ul><li>中间项目</li></ul>

before() / after() — 元素外部插入

javascript
function makeItem(text) {
  const li = document.createElement('li');
  li.textContent = text;
  return li;
}

const target = document.querySelector('.target');

target.before(makeItem('前面'));
target.after(makeItem('后面'));
html
<div class="target" style="border:1px solid #ccc;padding:8px">目标元素</div>

删除节点

javascript
const item = document.querySelector('li');
item.parentNode.removeChild(item);

const secondItem = document.querySelector('li');
secondItem.remove();
html
<ul><li>项目A</li><li>项目B</li><li>项目C</li></ul>

清空元素

javascript
const container = document.querySelector('.container');
container.innerHTML = '';
html
<div class="container">
  <p>段落1</p>
  <p>段落2</p>
  <p>段落3</p>
</div>

或逐个删除(避免 innerHTML 的性能和安全问题):

javascript
while (container.firstChild) {
  container.firstChild.remove();
}

替换和克隆

replaceWith() — 替换元素

javascript
const oldElement = document.querySelector('.old');
const newElement = document.createElement('div');
newElement.textContent = '新内容';
oldElement.replaceWith(newElement);
html
<div class="old">旧内容</div>

cloneNode() — 克隆元素

javascript
const original = document.querySelector('.template');
const clone = original.cloneNode(true);
const shallow = original.cloneNode(false);

clone.querySelector('.title').textContent = '副本的标题';
document.querySelector('#clone-output').appendChild(clone);
html
<div class="template">
  <p class="title">原始标题</p>
  <p>内容</p>
</div>
<div id="clone-output"></div>

cloneNode(true) 深克隆会复制所有子元素,非常适合模板化渲染。但注意克隆不会复制通过 addEventListener 绑定的事件监听器——需要为克隆后的元素重新绑定。

文档片段(DocumentFragment)

当需要批量插入大量元素时,使用 DocumentFragment 作为临时容器,最后一次性插入 DOM——减少回流,提升性能:

javascript
const fragment = document.createDocumentFragment();
const items = ['项目A', '项目B', '项目C', '项目D'];

for (const name of items) {
  const li = document.createElement('li');
  li.textContent = name;
  fragment.appendChild(li);
}

document.querySelector('ul').appendChild(fragment);
html
<ul></ul>

正常流程中,每插入一个元素浏览器就可能触发一次回流(reflow)。DocumentFragment 在内存中构建好所有元素,一次性添加到 DOM,只触发一次回流。对于几十个元素的批量插入,差异不大;但对于成百上千的元素,性能提升显著。

综合示例:Todo 列表

javascript
let todoId = 0;

function addTodo(text) {
  const li = document.createElement('li');
  li.className = 'todo-item';
  li.dataset.id = todoId++;

  li.innerHTML = `
    <span>${text}</span>
    <button class="delete-btn">删除</button>
  `;

  // 为删除按钮绑定事件(每个按钮独立绑定)
  li.querySelector('.delete-btn').addEventListener('click', () => {
    li.remove();
  });

  document.querySelector('#todo-list').appendChild(li);
}

// 使用
addTodo('学习 JavaScript');
addTodo('练习 DOM 操作');

document.querySelector('#add-btn').addEventListener('click', () => {
  const input = document.querySelector('#todo-input');
  if (input.value.trim()) {
    addTodo(input.value);
    input.value = '';
  }
});
html
<input id="todo-input" type="text" placeholder="输入待办事项">
<button id="add-btn">添加</button>
<ul id="todo-list"></ul>

这个简单示例涵盖了本章所有核心知识点——创建、插入、删除、事件绑定。