JavaScript学习教程,从入门到精通,DOM节点操作语法知识点及案例详解(21)

DOM节点操作语法知识点及案例详解

一、语法知识点

1. 获取节点

javascript 复制代码
// 通过ID获取
const element = document.getElementById('idName');

// 通过类名获取(返回HTMLCollection)
const elements = document.getElementsByClassName('className');

// 通过标签名获取(返回HTMLCollection)
const tags = document.getElementsByTagName('div');

// 通过CSS选择器获取单个元素
const el = document.querySelector('.selector');

// 通过CSS选择器获取所有匹配元素(返回NodeList)
const nodes = document.querySelectorAll('div.item');

// 特殊节点获取
document.documentElement;    // 获取html元素
document.head;               // 获取head元素
document.body;               // 获取body元素

2. 创建节点

javascript 复制代码
// 创建元素节点
const newDiv = document.createElement('div');

// 创建文本节点
const textNode = document.createTextNode('Hello World');

// 创建文档片段(优化批量操作)
const fragment = document.createDocumentFragment();

3. 添加节点

javascript 复制代码
// 末尾追加
parentNode.appendChild(childNode);

// 指定位置插入
parentNode.insertBefore(newNode, referenceNode);

// 插入HTML字符串(更灵活)
parentNode.insertAdjacentHTML('beforeend', '<div>New item</div>');
/*
位置参数:
'beforebegin':元素自身的前面
'afterbegin':插入元素内部的第一个子节点之前
'beforeend':插入元素内部的最后一个子节点之后
'afterend':元素自身的后面
*/

4. 删除节点

javascript 复制代码
// 传统方法(需要父节点)
parentNode.removeChild(childNode);

// 现代方法(直接操作)
childNode.remove();

// 清空所有子节点
while (container.firstChild) {
  container.removeChild(container.firstChild);
}

5. 克隆节点

javascript 复制代码
const cloneNode = originalNode.cloneNode(true); // true表示深度克隆

6. 节点关系

javascript 复制代码
node.parentNode;        // 父节点
node.childNodes;        // 子节点集合
node.firstChild;        // 第一个子节点
node.lastChild;         // 最后一个子节点
node.previousSibling;   // 前一个兄弟节点
node.nextSibling;       // 后一个兄弟节点

二、综合案例

案例1:线上点菜系统

html 复制代码
<!-- HTML结构 -->
<div class="container">
  <div class="menu">
    <h3>菜单列表</h3>
    <ul id="foodList">
      <li>鱼香肉丝 <span class="price">¥28</span></li>
      <li>宫保鸡丁 <span class="price">¥32</span></li>
      <li>麻婆豆腐 <span class="price">¥18</span></li>
    </ul>
  </div>
  
  <div class="ordered">
    <h3>已点菜品 <span id="total">总计:¥0</span></h3>
    <ul id="orderedList"></ul>
  </div>
</div>

<script>
// 初始化总价
let totalPrice = 0;

// 菜单点击事件委托
document.getElementById('foodList').addEventListener('click', function(e) {
  if (e.target.tagName === 'LI') {
    // 克隆选中的菜品
    const clonedItem = e.target.cloneNode(true);
    
    // 添加删除按钮
    const delBtn = document.createElement('button');
    delBtn.textContent = '×';
    delBtn.className = 'delete-btn';
    clonedItem.appendChild(delBtn);

    // 添加到已点列表
    document.getElementById('orderedList').appendChild(clonedItem);

    // 更新总价
    const price = parseFloat(e.target.querySelector('.price').textContent.slice(1));
    totalPrice += price;
    updateTotal();
  }
});

// 删除功能委托
document.getElementById('orderedList').addEventListener('click', function(e) {
  if (e.target.classList.contains('delete-btn')) {
    const listItem = e.target.parentElement;
    const price = parseFloat(listItem.querySelector('.price').textContent.slice(1));
    
    // 移除元素并更新总价
    listItem.remove();
    totalPrice -= price;
    updateTotal();
  }
});

function updateTotal() {
  document.getElementById('total').textContent = `总计:¥${totalPrice.toFixed(2)}`;
}
</script>

案例2:电商购物车

html 复制代码
<!-- HTML结构 -->
<div class="cart">
  <h2>购物车 <span id="cartTotal">¥0.00</span></h2>
  <ul id="cartList"></ul>
  <button id="addItem">添加商品</button>
</div>

<script>
class ShoppingCart {
  constructor() {
    this.items = [];
    this.cart = document.getElementById('cartList');
    this.init();
  }

  init() {
    // 添加示例商品
    this.addItem('iPhone 15', 7999);
    this.addItem('AirPods Pro', 1499);

    // 事件委托处理所有操作
    this.cart.addEventListener('click', (e) => {
      const itemEl = e.target.closest('.cart-item');
      if (!itemEl) return;

      const id = itemEl.dataset.id;
      const item = this.items.find(i => i.id == id);

      if (e.target.classList.contains('quantity-up')) {
        item.quantity++;
      } else if (e.target.classList.contains('quantity-down')) {
        if (item.quantity > 1) item.quantity--;
      } else if (e.target.classList.contains('delete-btn')) {
        this.removeItem(id);
      }

      this.updateItem(itemEl, item);
      this.updateTotal();
    });

    document.getElementById('addItem').addEventListener('click', () => {
      const name = prompt('请输入商品名称:');
      const price = parseFloat(prompt('请输入商品价格:'));
      if (name && price) this.addItem(name, price);
    });
  }

  addItem(name, price) {
    const newItem = {
      id: Date.now(),
      name,
      price,
      quantity: 1
    };
    this.items.push(newItem);
    this.renderItem(newItem);
    this.updateTotal();
  }

  renderItem(item) {
    const li = document.createElement('li');
    li.className = 'cart-item';
    li.dataset.id = item.id;
    li.innerHTML = `
      <span class="name">${item.name}</span>
      <div class="controls">
        <button class="quantity-down">-</button>
        <span class="quantity">${item.quantity}</span>
        <button class="quantity-up">+</button>
      </div>
      <span class="price">¥${(item.price * item.quantity).toFixed(2)}</span>
      <button class="delete-btn">删除</button>
    `;
    this.cart.appendChild(li);
  }

  updateItem(el, item) {
    el.querySelector('.quantity').textContent = item.quantity;
    el.querySelector('.price').textContent = `¥${(item.price * item.quantity).toFixed(2)}`;
  }

  removeItem(id) {
    this.items = this.items.filter(item => item.id != id);
    document.querySelector(`[data-id="${id}"]`).remove();
  }

  updateTotal() {
    const total = this.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
    document.getElementById('cartTotal').textContent = `¥${total.toFixed(2)}`;
  }
}

// 初始化购物车
new ShoppingCart();
</script>

三、关键知识点解析

  1. 事件委托:两个案例都使用了事件委托处理动态元素的事件,通过检查event.target来识别操作源

  2. 数据驱动:购物车案例将数据与DOM分离,保持数据源(this.items)与视图同步

  3. 克隆节点:点菜案例使用cloneNode(true)复制完整DOM结构

  4. 元素定位

    • closest() 方法查找最近的匹配祖先元素
    • dataset 属性操作自定义数据属性
  5. 数值处理

    • 使用toFixed(2)保持货币格式
    • 使用parseFloat处理价格转换
  6. 批量操作优化

    • 文档片段(document.createDocumentFragment)
    • 减少DOM操作次数(先计算后更新)

这些案例涵盖了DOM操作的核心知识点,实际开发中可结合CSS实现样式优化,并考虑添加本地存储功能实现数据持久化。

相关推荐
骑着小黑马几秒前
前端程序员自己的知识库,使用NodeJS+LLM搭建一个属于自己的知识库
前端·人工智能
wordbaby3 分钟前
加速 Web 应用:资源压缩详解与 Vite + Nginx 实践指南
前端·nginx·vite
Enti7c4 分钟前
如何编写JavaScript插件
javascript
神仙别闹6 分钟前
基于C++(MFC)的细胞识别程序
开发语言·c++·mfc
铭阳(●´∇`●)6 分钟前
Python内置函数---all()
笔记·python·学习
Tiger Z10 分钟前
R 语言科研绘图 --- 饼状图-汇总
开发语言·人工智能·程序人生·r语言·贴图
神仙别闹11 分钟前
基于C++(MFC)图形编辑界面工具
开发语言·c++·mfc
晓龙的Coding之路18 分钟前
python生成项目依赖文件requirements.txt
linux·开发语言·python
宝耶19 分钟前
HTML:表格数据展示区
前端·html
程序员海军33 分钟前
一键把网站变成吉卜力风格的神器来了
前端·chatgpt