问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

前端开发入门:DOM操作基础与实践

创作时间:
作者:
@小白创作中心

前端开发入门:DOM操作基础与实践

引用
CSDN
1.
https://blog.csdn.net/speaking_me/article/details/146068406

在前端开发中,DOM操作是实现页面动态交互的基础。本文将从DOM的核心概念、基本操作、事件处理机制等方面进行详细讲解,并通过一个动态表格案例进行实践。

一、DOM核心概念

1.1 DOM树结构

DOM(Document Object Model)将HTML文档表示为树形结构,由多个节点组成:

  • 文档节点:整个文档的根节点
  • 元素节点:HTML标签
  • 属性节点:元素的属性
  • 文本节点:元素包含的文本内容
  • 注释节点:HTML注释

1.2 节点类型

每个DOM节点都有nodeType属性:

Node.ELEMENT_NODE(1)   // 元素节点
Node.ATTRIBUTE_NODE(2) // 属性节点
Node.TEXT_NODE(3)      // 文本节点
// ...其他类型

1.3 节点关系

  • parentNode
  • childNodes
  • firstChild/lastChild
  • nextSibling/previousSibling

二、基本DOM操作

2.1 元素选择

// 传统方法
document.getElementById('id')
document.getElementsByClassName('class')
document.getElementsByTagName('div')
// 现代选择器
document.querySelector('#id') // 返回单个元素
document.querySelectorAll('.class') // 返回NodeList

2.2 元素创建/修改

// 创建元素
const newDiv = document.createElement('div')
const textNode = document.createTextNode('Hello')
// 属性操作
element.setAttribute('data-id', '123')
element.classList.add('active')
element.style.color = 'red'
// 内容操作
element.innerHTML = '<span>内容</span>'
element.textContent = '纯文本内容'

2.3 节点操作

// 插入节点
parent.appendChild(child)
parent.insertBefore(newNode, referenceNode)
// 移除节点
parent.removeChild(child)
element.remove()
// 替换节点
parent.replaceChild(newChild, oldChild)

三、事件处理机制

3.1 事件流三个阶段

  1. 捕获阶段(从上到下)
  2. 目标阶段
  3. 冒泡阶段(从下到上)

3.2 事件绑定

// 传统方式
button.onclick = function() {}
// 现代方式
element.addEventListener('click', handler, useCapture)

3.3 事件对象

element.addEventListener('click', function(e) {
    e.preventDefault() // 阻止默认行为
    e.stopPropagation() // 阻止冒泡
    console.log(e.target) // 事件源
})

四、动态表格案例

4.1 核心代码

<!DOCTYPE html>
<html>
<head>
    <style>
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; cursor: pointer; }
        tr:hover { background-color: #f5f5f5; }
        .delete-btn { color: red; cursor: pointer; }
    </style>
</head>
<body>
    <div id="controls">
        <button onclick="sortTable('name')">按姓名排序</button>
        <button onclick="sortTable('age')">按年龄排序</button>
    </div>
    <table id="dataTable">
        <thead>
            <tr>
                <th>姓名</th>
                <th>年龄</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody id="tableBody"></tbody>
    </table>
    <script>
        // 初始数据
        let data = [
            { name: '王小明', age: 25 },
            { name: '李华', age: 30 },
            { name: '张强', age: 22 }
        ];
        // 渲染表格
        function renderTable() {
            const tbody = document.getElementById('tableBody');
            tbody.innerHTML = '';
            
            // 使用文档片段优化性能
            const fragment = document.createDocumentFragment();
            
            data.forEach((item, index) => {
                const row = document.createElement('tr');
                
                // 姓名列
                const nameCell = document.createElement('td');
                nameCell.textContent = item.name;
                
                // 年龄列
                const ageCell = document.createElement('td');
                ageCell.textContent = item.age;
                
                // 操作列
                const actionCell = document.createElement('td');
                const deleteBtn = document.createElement('span');
                deleteBtn.className = 'delete-btn';
                deleteBtn.textContent = '删除';
                deleteBtn.onclick = () => deleteRow(index);
                
                actionCell.appendChild(deleteBtn);
                
                row.appendChild(nameCell);
                row.appendChild(ageCell);
                row.appendChild(actionCell);
                fragment.appendChild(row);
            });
            
            tbody.appendChild(fragment);
        }
        // 删除行
        function deleteRow(index) {
            data.splice(index, 1);
            renderTable();
        }
        // 表格排序
        function sortTable(field) {
            data.sort((a, b) => {
                if (typeof a[field] === 'string') {
                    return a[field].localeCompare(b[field]);
                }
                return a[field] - b[field];
            });
            renderTable();
        }
        // 初始渲染
        renderTable();
    </script>
</body>
</html>

4.2 实现效果

  • 初始显示数据表格
  • 点击表头排序(姓名/年龄)
  • 删除行操作
  • 鼠标悬停高亮效果

4.3 学习要点总结

  1. DOM操作基础
  • 元素选择方法对比:querySelector vs getElementById
  • 创建元素的两种方式:innerHTML vs createElement
  • 文档片段优化批量插入

2.事件处理

  • 事件委托的优势

  • 动态元素的事件绑定
  • 事件冒泡与阻止传播

3.性能优化

  • 减少重排次数
  • 合理使用事件委托
  • 避免频繁操作DOM

4.数据驱动视图

  • 保持数据与视图同步
  • 单向数据流实现
  • 响应式更新策略

4.4 扩展阅读推荐

官方文档

  1. MDN DOM文档
  2. W3C DOM规范
  3. DOM Living Standard

优质文章

  1. JavaScript性能优化之DOM操作
  2. 深入理解浏览器渲染原理
  3. 事件委托的原理与实践
  4. 现代JavaScript开发中的DOM操作最佳实践

推荐书籍

  1. 《JavaScript高级程序设计》(第4版)- DOM相关章节
  2. 《你不知道的JavaScript》(中卷)- 异步与性能
  3. 《高性能JavaScript》- 第3章 DOM编程

五、进阶技巧

  1. MutationObserver的使用
const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
        console.log('DOM发生变化:', mutation);
    });
});
observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: true
});
  1. 虚拟DOM原理
  • 通过JavaScript对象模拟DOM结构
  • 差异比较算法(Diff算法)
  • 批量更新机制
  1. 性能检测工具
  • Chrome DevTools的Performance面板
  • Lighthouse性能审计
  • requestAnimationFrame优化动画

通过本文的学习,读者应该能够掌握DOM操作的核心概念,理解事件处理机制,并能够实现常见的动态交互功能。建议结合实际项目需求,继续探索更复杂的DOM操作场景和优化策略。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号