Skip to content

DOM 进阶:节点操作

15.1 节点层级:父节点 / 子节点 / 兄弟节点

在 DOM 树中,元素之间存在层级关系,我们可以通过各种属性来访问这些关系。

父节点(Parent Node)

javascript
const child = document.getElementById("child");
const parent = child.parentNode; // 获取父节点
console.log(parent);

子节点(Child Nodes)

javascript
const parent = document.getElementById("parent");

// 获取所有子节点(包括文本节点)
const childNodes = parent.childNodes;
console.log(childNodes.length);

// 获取所有子元素(只包括元素节点)
const children = parent.children;
console.log(children.length);

// 获取第一个子元素
const firstChild = parent.firstElementChild;
console.log(firstChild);

// 获取最后一个子元素
const lastChild = parent.lastElementChild;
console.log(lastChild);

兄弟节点(Sibling Nodes)

javascript
const element = document.getElementById("element");

// 获取前一个兄弟元素
const previousSibling = element.previousElementSibling;
console.log(previousSibling);

// 获取后一个兄弟元素
const nextSibling = element.nextElementSibling;
console.log(nextSibling);

15.2 创建 / 添加 / 删除 / 克隆节点

创建节点

创建元素节点

javascript
// 创建一个 div 元素
const newDiv = document.createElement("div");
newDiv.textContent = "这是一个新创建的 div";
newDiv.className = "new-box";

创建文本节点

javascript
// 创建一个文本节点
const textNode = document.createTextNode("这是一段文本");

添加节点

appendChild() 方法

将节点添加到父节点的末尾。

javascript
const parent = document.getElementById("parent");
const newDiv = document.createElement("div");
newDiv.textContent = "新添加的元素";

// 添加到父节点末尾
parent.appendChild(newDiv);

insertBefore() 方法

在指定节点前插入新节点。

javascript
const parent = document.getElementById("parent");
const referenceNode = document.getElementById("reference");
const newDiv = document.createElement("div");
newDiv.textContent = "插入的元素";

// 在 referenceNode 前插入新节点
parent.insertBefore(newDiv, referenceNode);

删除节点

removeChild() 方法

删除指定的子节点。

javascript
const parent = document.getElementById("parent");
const child = document.getElementById("child");

// 删除子节点
parent.removeChild(child);

remove() 方法(ES6+)

直接删除节点自身。

javascript
const element = document.getElementById("element");
element.remove();

克隆节点

cloneNode() 方法

克隆节点,参数为 true 时会克隆所有子节点,为 false 时只克隆节点本身。

javascript
const original = document.getElementById("original");

// 浅克隆(只克隆节点本身)
const shallowClone = original.cloneNode(false);

// 深克隆(克隆节点及其所有子节点)
const deepClone = original.cloneNode(true);

// 将克隆的节点添加到文档中
const parent = document.getElementById("parent");
parent.appendChild(deepClone);

15.3 实战:动态添加列表项 / 删除商品

实战 1:动态添加列表项

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>动态添加列表项</title>
</head>
<body>
  <input type="text" id="inputItem" placeholder="请输入列表项">
  <button id="addBtn">添加</button>
  <ul id="list"></ul>

  <script>
    const inputItem = document.getElementById("inputItem");
    const addBtn = document.getElementById("addBtn");
    const list = document.getElementById("list");

    addBtn.addEventListener("click", function() {
      const itemText = inputItem.value.trim();
      if (itemText) {
        // 创建新的 li 元素
        const li = document.createElement("li");
        
        // 设置 li 的内容
        li.textContent = itemText;
        
        // 创建删除按钮
        const deleteBtn = document.createElement("button");
        deleteBtn.textContent = "删除";
        deleteBtn.style.marginLeft = "10px";
        
        // 添加删除事件
        deleteBtn.addEventListener("click", function() {
          li.remove();
        });
        
        // 将删除按钮添加到 li 中
        li.appendChild(deleteBtn);
        
        // 将 li 添加到列表中
        list.appendChild(li);
        
        // 清空输入框
        inputItem.value = "";
      }
    });
  </script>
</body>
</html>

实战 2:删除商品

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>删除商品</title>
  <style>
    .product {
      display: flex;
      align-items: center;
      padding: 10px;
      border-bottom: 1px solid #eee;
    }
    .product-name {
      flex: 1;
    }
    .delete-btn {
      background-color: #ff4444;
      color: white;
      border: none;
      padding: 5px 10px;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <h2>商品列表</h2>
  <div id="productList">
    <div class="product">
      <div class="product-name">商品 1</div>
      <button class="delete-btn">删除</button>
    </div>
    <div class="product">
      <div class="product-name">商品 2</div>
      <button class="delete-btn">删除</button>
    </div>
    <div class="product">
      <div class="product-name">商品 3</div>
      <button class="delete-btn">删除</button>
    </div>
  </div>

  <script>
    const deleteBtns = document.querySelectorAll(".delete-btn");
    
    deleteBtns.forEach(btn => {
      btn.addEventListener("click", function() {
        // 获取当前按钮所在的商品行
        const product = this.parentNode;
        // 删除商品行
        product.remove();
      });
    });
  </script>
</body>
</html>

实战 3:动态创建表格行

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>动态创建表格行</title>
  <style>
    table {
      border-collapse: collapse;
      width: 100%;
    }
    th, td {
      border: 1px solid #ddd;
      padding: 8px;
      text-align: left;
    }
    th {
      background-color: #f2f2f2;
    }
    .add-btn {
      margin: 10px 0;
      padding: 5px 10px;
    }
  </style>
</head>
<body>
  <button id="addRowBtn" class="add-btn">添加行</button>
  <table id="myTable">
    <thead>
      <tr>
        <th>姓名</th>
        <th>年龄</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody id="tableBody">
      <tr>
        <td>张三</td>
        <td>25</td>
        <td><button class="delete-btn">删除</button></td>
      </tr>
      <tr>
        <td>李四</td>
        <td>30</td>
        <td><button class="delete-btn">删除</button></td>
      </tr>
    </tbody>
  </table>

  <script>
    const addRowBtn = document.getElementById("addRowBtn");
    const tableBody = document.getElementById("tableBody");
    let rowCount = 2;

    addRowBtn.addEventListener("click", function() {
      rowCount++;
      
      // 创建新行
      const row = document.createElement("tr");
      
      // 创建姓名单元格
      const nameCell = document.createElement("td");
      nameCell.textContent = `用户 ${rowCount}`;
      
      // 创建年龄单元格
      const ageCell = document.createElement("td");
      ageCell.textContent = 20 + Math.floor(Math.random() * 10);
      
      // 创建操作单元格
      const actionCell = document.createElement("td");
      const deleteBtn = document.createElement("button");
      deleteBtn.textContent = "删除";
      deleteBtn.className = "delete-btn";
      
      // 添加删除事件
      deleteBtn.addEventListener("click", function() {
        row.remove();
      });
      
      actionCell.appendChild(deleteBtn);
      
      // 将单元格添加到行中
      row.appendChild(nameCell);
      row.appendChild(ageCell);
      row.appendChild(actionCell);
      
      // 将行添加到表格体中
      tableBody.appendChild(row);
    });

    // 为现有的删除按钮添加事件
    document.querySelectorAll(".delete-btn").forEach(btn => {
      btn.addEventListener("click", function() {
        this.parentNode.parentNode.remove();
      });
    });
  </script>
</body>
</html>

节点类型

DOM 中的节点类型有多种,常见的包括:

节点类型常量描述
元素节点1HTML 元素,如 <div><p>
文本节点3元素内的文本内容
属性节点2元素的属性
注释节点8注释内容
文档节点9整个 HTML 文档

可以通过 nodeType 属性获取节点类型:

javascript
const element = document.getElementById("myElement");
console.log(element.nodeType); // 输出:1(元素节点)

const text = element.firstChild;
console.log(text.nodeType); // 输出:3(文本节点)

小结

  • DOM 树中元素之间存在层级关系:父节点、子节点、兄弟节点
  • 访问节点关系的属性:parentNodechildrenfirstElementChildlastElementChildpreviousElementSiblingnextElementSibling
  • 创建节点:createElement()createTextNode()
  • 添加节点:appendChild()insertBefore()
  • 删除节点:removeChild()remove()
  • 克隆节点:cloneNode()
  • 动态操作节点是实现交互式网页的重要手段,如添加列表项、删除商品等
  • 理解节点类型有助于更精确地操作 DOM

© 2026 编程马·菜鸟教程 版权所有