您现在的位置是:网站首页 > DOM节点操作文章详情
DOM节点操作
陈川
【
JavaScript
】
5413人已围观
6054字
DOM节点操作是JavaScript中处理网页内容的核心技术之一。通过创建、修改、删除和查询DOM节点,开发者可以动态改变页面结构和行为。
DOM节点基础概念
DOM(Document Object Model)将HTML文档表示为树状结构,每个HTML元素都是一个节点。常见的节点类型包括:
- 元素节点(如
<div>
) - 文本节点(元素内的文字内容)
- 属性节点(如
class="container"
) - 注释节点
// 获取文档根节点
const root = document.documentElement;
// 检查节点类型
console.log(root.nodeType); // 1 (元素节点)
console.log(root.nodeName); // "HTML"
节点查询方法
基本查询方法
// 通过ID获取
const header = document.getElementById('header');
// 通过类名获取(返回HTMLCollection)
const items = document.getElementsByClassName('item');
// 通过标签名获取
const divs = document.getElementsByTagName('div');
现代选择器API
// 返回匹配的第一个元素
const button = document.querySelector('.btn-primary');
// 返回所有匹配元素(NodeList)
const images = document.querySelectorAll('img.thumbnail');
// 在元素范围内查询
const container = document.getElementById('container');
const innerDivs = container.querySelectorAll('div');
节点创建与添加
创建新节点
// 创建元素节点
const newDiv = document.createElement('div');
// 创建文本节点
const textNode = document.createTextNode('Hello World');
// 创建属性节点
const attr = document.createAttribute('data-custom');
attr.value = 'value';
添加节点到DOM
// 追加子节点
const parent = document.getElementById('parent');
parent.appendChild(newDiv);
// 插入到特定位置
const firstChild = parent.firstChild;
parent.insertBefore(newDiv, firstChild);
// 使用insertAdjacentHTML
parent.insertAdjacentHTML('beforeend', '<span>New content</span>');
节点修改操作
修改属性
// 标准属性
const img = document.querySelector('img');
img.src = 'new-image.jpg';
img.alt = 'Description';
// 自定义属性
img.dataset.userId = '12345';
// class操作
img.classList.add('active');
img.classList.remove('inactive');
img.classList.toggle('visible');
修改内容
// innerHTML(注意XSS风险)
div.innerHTML = '<strong>Warning!</strong>';
// textContent(安全)
div.textContent = 'Plain text content';
// innerText(考虑样式)
div.innerText = 'Only visible text';
节点删除与替换
// 删除节点
const oldChild = parent.removeChild(parent.lastChild);
// 替换节点
const newParagraph = document.createElement('p');
newParagraph.textContent = 'New content';
parent.replaceChild(newParagraph, parent.firstChild);
// 现代方法
parent.firstElementChild.replaceWith(newParagraph);
parent.lastElementChild.remove();
节点遍历与关系
// 父节点
const child = document.querySelector('.child');
const parent = child.parentNode;
// 子节点
const children = parent.childNodes; // 包含所有节点类型
const elementChildren = parent.children; // 仅元素节点
// 兄弟节点
const nextSibling = child.nextSibling;
const prevSibling = child.previousSibling;
// 元素专用遍历
const nextElement = child.nextElementSibling;
const prevElement = child.previousElementSibling;
事件委托与节点操作
// 事件委托示例
document.getElementById('list').addEventListener('click', function(e) {
if(e.target.tagName === 'LI') {
e.target.classList.toggle('completed');
}
});
// 动态添加事件
const newButton = document.createElement('button');
newButton.textContent = 'Click me';
newButton.addEventListener('click', () => {
alert('Button clicked!');
});
document.body.appendChild(newButton);
性能优化技巧
- 文档片段:减少重排次数
const fragment = document.createDocumentFragment();
for(let i = 0; i < 100; i++) {
const item = document.createElement('div');
item.textContent = `Item ${i}`;
fragment.appendChild(item);
}
document.getElementById('container').appendChild(fragment);
- 批量修改:先脱离DOM树再操作
const tempParent = document.createElement('div');
const element = document.getElementById('to-modify');
tempParent.appendChild(element);
// 执行大量修改
element.style.width = '200px';
// ...其他修改
document.body.appendChild(element);
- 选择器性能:ID选择器最快,复杂选择器较慢
现代DOM操作API
MutationObserver
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
console.log('DOM changed:', mutation.type);
});
});
observer.observe(document.getElementById('observable'), {
attributes: true,
childList: true,
subtree: true
});
Element.closest()
// 查找最近的匹配祖先
const listItem = document.querySelector('li');
const containingList = listItem.closest('ul');
常见问题与解决方案
动态内容加载后选择
// 错误:在元素存在前尝试选择
const missingElement = document.getElementById('not-yet-loaded');
// 解决方案1:确保DOM加载完成
document.addEventListener('DOMContentLoaded', () => {
const element = document.getElementById('now-available');
});
// 解决方案2:MutationObserver监听特定区域
内存泄漏
// 移除元素前清理事件
const element = document.getElementById('leaky');
const handler = () => console.log('Clicked');
element.addEventListener('click', handler);
// 正确移除
element.removeEventListener('click', handler);
element.remove();
实际应用案例
动态表格生成
function createTable(data) {
const table = document.createElement('table');
const thead = table.createTHead();
const tbody = table.createTBody();
// 创建表头
const headerRow = thead.insertRow();
Object.keys(data[0]).forEach(key => {
const th = document.createElement('th');
th.textContent = key;
headerRow.appendChild(th);
});
// 填充数据
data.forEach(item => {
const row = tbody.insertRow();
Object.values(item).forEach(value => {
const cell = row.insertCell();
cell.textContent = value;
});
});
return table;
}
无限滚动实现
window.addEventListener('scroll', () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 500) {
loadMoreContent();
}
});
async function loadMoreContent() {
const response = await fetch('/api/more-items');
const items = await response.json();
const container = document.getElementById('items-container');
items.forEach(item => {
const element = document.createElement('div');
element.className = 'item';
element.innerHTML = `
<h3>${item.title}</h3>
<p>${item.description}</p>
`;
container.appendChild(element);
});
}