JavaScript — DOM

DOM

This article is extracted from the chat log with AI. Please identify it with caution.

JavaScript DOM API 全面介绍 #

DOM(文档对象模型)是HTML和XML文档的编程接口,它提供了对文档的结构化表示,并定义了一种方式使程序可以访问和操作文档的结构、样式和内容。

下面我将按功能分类介绍主要的DOM API,并提供相应的代码示例。

1. 节点查询与选择 #

按ID查询 #

// 获取元素
const element = document.getElementById('myElement');
console.log(element);

按类名查询 #

// 获取多个元素(HTMLCollection)
const elements = document.getElementsByClassName('myClass');
console.log(elements);

// 转换为数组操作
const elementsArray = Array.from(elements);
elementsArray.forEach(el => console.log(el));

按标签名查询 #

// 获取所有div元素
const divs = document.getElementsByTagName('div');
console.log(divs);

使用CSS选择器(querySelectorAll) #

// 查询单个元素
const firstItem = document.querySelector('.item:first-child');
console.log(firstItem);

// 查询多个元素
const allItems = document.querySelectorAll('.item');
allItems.forEach(item => console.log(item));

2. DOM遍历与导航 #

// 父节点
const parent = element.parentNode;

// 子节点
const children = element.childNodes;
const firstChild = element.firstChild;
const lastChild = element.lastChild;

// 兄弟节点
const nextSibling = element.nextSibling;
const previousSibling = element.previousSibling;

// 元素专用导航(忽略文本节点等)
const parentElement = element.parentElement;
const childrenElements = element.children;
const firstElementChild = element.firstElementChild;
const lastElementChild = element.lastElementChild;
const nextElementSibling = element.nextElementSibling;
const previousElementSibling = element.previousElementSibling;

3. DOM操作与修改 #

创建元素 #

// 创建新元素
const newDiv = document.createElement('div');
newDiv.textContent = '我是新创建的div元素';
newDiv.className = 'new-div';

// 创建文本节点
const newText = document.createTextNode('这是一段文本内容');

添加元素(appendChild) #

// 追加到父元素末尾
parentElement.appendChild(newDiv);

// 插入到特定位置
parentElement.insertBefore(newDiv, referenceElement);

// 使用现代API
parentElement.append(newDiv, "一些文本"); // 可以添加多个节点和文本
parentElement.prepend(newDiv); // 添加到开头

替换元素 #

// 替换子元素
parentElement.replaceChild(newDiv, oldDiv);

删除元素 #

// 移除子元素
parentElement.removeChild(oldDiv);

// 现代方法
oldDiv.remove();

克隆元素 #

// 浅克隆(不包含子元素)
const shallowClone = element.cloneNode(false);

// 深克隆(包含所有子元素)
const deepClone = element.cloneNode(true);

4. 属性操作 #

// 获取属性
const value = element.getAttribute('data-custom');

// 设置属性
element.setAttribute('data-custom', 'new-value');

// 检查属性
const hasAttribute = element.hasAttribute('data-custom');

// 移除属性
element.removeAttribute('data-custom');

// data-* 属性专用接口
console.log(element.dataset.custom); // 获取
element.dataset.custom = 'new-value'; // 设置

// 类名操作
element.classList.add('new-class');
element.classList.remove('old-class');
element.classList.toggle('active');
element.classList.contains('check-class');

5. 样式操作 #

// 直接操作样式
element.style.color = 'blue';
element.style.backgroundColor = '#f0f0f0';
element.style.fontSize = '16px';

// 批量修改样式
element.style.cssText = 'color: blue; background-color: #f0f0f0; font-size: 16px;';

// 获取计算样式
const computedStyle = window.getComputedStyle(element);
console.log(computedStyle.color);

6. 内容操作 #

// 获取/设置HTML内容
console.log(element.innerHTML);
element.innerHTML = '<span>新内容</span>';

// 获取/设置文本内容
console.log(element.textContent);
element.textContent = '新的文本内容';

// 获取/设置值(表单元素)
console.log(inputElement.value);
inputElement.value = '新的值';

7. 事件处理 #

// 添加事件监听器
function handleClick(event) {
  console.log('元素被点击了', event.target);
  event.stopPropagation(); // 阻止事件冒泡
}

element.addEventListener('click', handleClick);

// 移除事件监听器
element.removeEventListener('click', handleClick);

// 事件对象常用属性和方法
element.addEventListener('click', (event) => {
  console.log(event.target); // 事件目标
  console.log(event.currentTarget); // 当前处理元素
  console.log(event.type); // 事件类型
  event.preventDefault(); // 阻止默认行为
});

// 事件委托示例
document.getElementById('list').addEventListener('click', (event) => {
  if (event.target.tagName === 'LI') {
    console.log('列表项被点击:', event.target.textContent);
  }
});

8. 表单操作 #

// 获取表单元素
const form = document.forms['myForm'];
const input = form.elements['username'];

// 表单提交事件
form.addEventListener('submit', (event) => {
  event.preventDefault(); // 阻止默认提交
  console.log('表单值:', input.value);
  // 可以在这里进行验证或AJAX提交
});

// 表单验证
input.addEventListener('input', (event) => {
  if (input.value.length < 3) {
    input.setCustomValidity('用户名至少需要3个字符');
  } else {
    input.setCustomValidity('');
  }
});

完整示例 #

下面是一个综合使用多种DOM API的示例:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DOM API 示例</title>
  <style>
    body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
    .item { padding: 10px; margin: 5px 0; background: #f0f0f0; border-radius: 4px; }
    .highlight { background: #ffd700; }
    .new-item { background: #d4edda; }
    button { margin: 5px; padding: 8px 12px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
    button:hover { background: #0056b3; }
  </style>
</head>
<body>
  <h1>DOM API 演示</h1>
  
  <div id="container">
    <div class="item">项目 1</div>
    <div class="item">项目 2</div>
    <div class="item">项目 3</div>
  </div>
  
  <button id="addBtn">添加项目</button>
  <button id="removeBtn">删除最后一个项目</button>
  <button id="highlightBtn">高亮第一个项目</button>
  
  <script>
    // 获取元素
    const container = document.getElementById('container');
    const addBtn = document.getElementById('addBtn');
    const removeBtn = document.getElementById('removeBtn');
    const highlightBtn = document.getElementById('highlightBtn');
    
    // 计数器
    let itemCount = 3;
    
    // 添加项目
    addBtn.addEventListener('click', () => {
      itemCount++;
      const newItem = document.createElement('div');
      newItem.className = 'item new-item';
      newItem.textContent = `项目 ${itemCount}`;
      
      // 添加动画效果
      newItem.style.opacity = '0';
      container.appendChild(newItem);
      
      // 使用requestAnimationFrame实现淡入效果
      let opacity = 0;
      const fadeIn = () => {
        opacity += 0.05;
        newItem.style.opacity = opacity.toString();
        if (opacity < 1) {
          requestAnimationFrame(fadeIn);
        }
      };
      requestAnimationFrame(fadeIn);
    });
    
    // 删除最后一个项目
    removeBtn.addEventListener('click', () => {
      const lastItem = container.lastElementChild;
      if (lastItem) {
        // 添加淡出效果后再删除
        let opacity = 1;
        const fadeOut = () => {
          opacity -= 0.05;
          lastItem.style.opacity = opacity.toString();
          if (opacity > 0) {
            requestAnimationFrame(fadeOut);
          } else {
            lastItem.remove();
          }
        };
        requestAnimationFrame(fadeOut);
      }
    });
    
    // 高亮第一个项目
    highlightBtn.addEventListener('click', () => {
      const firstItem = container.querySelector('.item');
      if (firstItem) {
        firstItem.classList.toggle('highlight');
      }
    });
    
    // 事件委托 - 点击项目时触发
    container.addEventListener('click', (event) => {
      if (event.target.classList.contains('item')) {
        console.log('点击了:', event.target.textContent);
        event.target.style.textDecoration = event.target.style.textDecoration === 'line-through' ? '' : 'line-through';
      }
    });
  </script>
</body>
</html>

总结 #

DOM API提供了丰富的方法来操作网页内容、结构和样式。关键点包括:

  1. 使用querySelector和querySelectorAll进行现代元素选择
  2. 掌握节点操作(创建、添加、删除、替换)
  3. 合理使用classList进行类名操作
  4. 利用事件委托提高性能
  5. 使用dataset操作data-*属性

在实际开发中,应优先使用现代DOM API,它们更简洁、性能更好,并注意跨浏览器兼容性问题。

querySelector 与 getElementBy 系列方法的区别 #

下面我将详细解释这两种DOM查询方法的区别,并通过一个可视化示例展示它们的不同特性。

核心区别对比 #

特性querySelector/querySelectorAllgetElementBy 系列
返回值类型NodeList (静态)HTMLCollection (动态) 或 单个元素
选择器灵活性支持任何CSS选择器仅支持ID、类名、标签名
返回结果总是返回NodeList,即使只有一个元素可能返回单个元素或集合
实时性静态集合,不随DOM变化自动更新动态集合,随DOM变化自动更新
性能复杂选择器可能稍慢简单选择通常更快

关键区别解释 #

1. 返回值类型 #

  • querySelectorAll 返回一个静态的 NodeList
  • getElementsByClassNamegetElementsByTagName 返回一个动态的 HTMLCollection

2. 实时性 #

  • 静态集合(querySelectorAll)在创建后不会变化,即使DOM发生了变化
  • 动态集合(getElementBy系列)会自动更新反映DOM的变化

3. 灵活性 #

  • querySelector 支持复杂的CSS选择器(如"div.item:first-child")
  • getElementBy 系列只支持简单的ID、类名或标签名

4. 性能 #

  • getElementById 是速度最快的方法
  • 简单选择时 getElementsByClassName 比 querySelectorAll 更快
  • 复杂选择时 querySelectorAll 更合适

使用建议 #

  1. 按ID选择元素时,使用 getElementById(最快)
  2. 需要复杂CSS选择器时,使用 querySelectorquerySelectorAll
  3. 按类名选择且需要实时更新时,使用 getElementsByClassName
  4. 按标签名选择且需要实时更新时,使用 getElementsByTagName

在实际开发中,可以根据具体需求选择最适合的方法,也可以组合使用这些方法以达到最佳效果。

参考资料 #

JavaScript DOM编程艺术

本文共 2531 字,创建于 Sep 6, 2025

相关标签: Frontend, ByAI, JavaScript, CSS, HTML, TypeScript