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提供了丰富的方法来操作网页内容、结构和样式。关键点包括:
- 使用querySelector和querySelectorAll进行现代元素选择
- 掌握节点操作(创建、添加、删除、替换)
- 合理使用classList进行类名操作
- 利用事件委托提高性能
- 使用dataset操作data-*属性
在实际开发中,应优先使用现代DOM API,它们更简洁、性能更好,并注意跨浏览器兼容性问题。
querySelector 与 getElementBy 系列方法的区别 #
下面我将详细解释这两种DOM查询方法的区别,并通过一个可视化示例展示它们的不同特性。
核心区别对比 #
特性 | querySelector/querySelectorAll | getElementBy 系列 |
---|---|---|
返回值类型 | NodeList (静态) | HTMLCollection (动态) 或 单个元素 |
选择器灵活性 | 支持任何CSS选择器 | 仅支持ID、类名、标签名 |
返回结果 | 总是返回NodeList,即使只有一个元素 | 可能返回单个元素或集合 |
实时性 | 静态集合,不随DOM变化自动更新 | 动态集合,随DOM变化自动更新 |
性能 | 复杂选择器可能稍慢 | 简单选择通常更快 |
关键区别解释 #
1. 返回值类型 #
querySelectorAll
返回一个静态的 NodeListgetElementsByClassName
和getElementsByTagName
返回一个动态的 HTMLCollection
2. 实时性 #
- 静态集合(querySelectorAll)在创建后不会变化,即使DOM发生了变化
- 动态集合(getElementBy系列)会自动更新反映DOM的变化
3. 灵活性 #
- querySelector 支持复杂的CSS选择器(如"div.item:first-child")
- getElementBy 系列只支持简单的ID、类名或标签名
4. 性能 #
- getElementById 是速度最快的方法
- 简单选择时 getElementsByClassName 比 querySelectorAll 更快
- 复杂选择时 querySelectorAll 更合适
使用建议 #
- 按ID选择元素时,使用
getElementById
(最快) - 需要复杂CSS选择器时,使用
querySelector
或querySelectorAll
- 按类名选择且需要实时更新时,使用
getElementsByClassName
- 按标签名选择且需要实时更新时,使用
getElementsByTagName
在实际开发中,可以根据具体需求选择最适合的方法,也可以组合使用这些方法以达到最佳效果。