您现在的位置是:网站首页 > DOM节点操作文章详情

DOM节点操作

DOM节点操作是JavaScript中处理网页内容的核心技术之一。通过创建、修改、删除和查询DOM节点,开发者可以动态改变页面结构和行为。

DOM节点基础概念

DOM(Document Object Model)将HTML文档表示为树状结构,每个HTML元素都是一个节点。常见的节点类型包括:

  1. 元素节点(如<div>
  2. 文本节点(元素内的文字内容)
  3. 属性节点(如class="container"
  4. 注释节点
// 获取文档根节点
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);

性能优化技巧

  1. 文档片段:减少重排次数
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);
  1. 批量修改:先脱离DOM树再操作
const tempParent = document.createElement('div');
const element = document.getElementById('to-modify');
tempParent.appendChild(element);

// 执行大量修改
element.style.width = '200px';
// ...其他修改

document.body.appendChild(element);
  1. 选择器性能: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);
  });
}

上一篇: DOM查询方法

下一篇: 地图(Map)实现

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步