导读:本期聚焦于小诸葛创作的《JavaScript DOM操作有哪些常用方法?前端开发入门必看指南》,敬请观看详情。DOM是前端开发中与页面交互的核心接口,JavaScript通过DOM操作可以实现页面元素的增删改查、属性修改、事件绑定等功能。很多刚入门的前端开发者对DOM操作的常用方法和使用场景不够熟悉,不知道如何高效操作页面元素。本文整理了JavaScript DOM操作的常见方法,包含元素获取、内容修改、节点操作、事件处理等实用内容,搭配代码示例帮助开发者快速掌握DOM操作的核心技巧,提升前端开发效率。

JavaScript DOM操作是前端开发中实现页面动态交互的核心能力。文档对象模型将HTML文档解析为可编程的对象树,开发者通过JavaScript可以访问和修改页面中的元素、内容、属性与样式,让静态页面具备响应式交互。无论是列表渲染、表单校验、动画控制,还是单页应用的路由切换,都离不开对DOM的熟练操作。

JavaScript DOM操作常用方法

一、认识DOM树与节点类型

DOM全称Document Object Model,即文档对象模型,它并不是JavaScript语言的一部分,而是浏览器提供的一套编程接口。当浏览器加载一个HTML文档时,会解析文档结构并生成一棵对象树,树中的每一个分支都可以视为一个节点。JavaScript通过操作这些节点对象,就能实现在不刷新页面的前提下更新界面。

在DOM树中,常见的节点类型主要包含三类:元素节点对应HTML中的标签,例如<div>、<p>、<span>等;文本节点表示元素内部包含的纯文本内容;属性节点则描述元素携带的属性,如class、id、data-*等。理解这些节点类型有助于在后续的节点查找、创建和修改过程中明确操作对象。

除节点类型外,DOM节点之间还存在父子关系与兄弟关系。一个元素节点的直接子节点可以通过childNodes或children属性访问,父节点可以通过parentNode访问,相邻节点则可以通过previousSibling和nextSibling获取。这些关系在节点遍历与插入删除操作中非常实用,能够帮助开发者精确定位目标节点。

二、获取页面元素的核心方法

在操作DOM之前,首先需要获取目标元素。JavaScript提供了一系列方法用于元素查找,其中最常用的包括getElementByIdgetElementsByClassNamequerySelector以及querySelectorAll。不同方法适用于不同场景,选择合适的方法能提高代码的可读性和性能。

getElementById根据元素id属性查找,返回唯一的元素对象。由于id在页面中应当保持唯一,所以该方法返回单个节点;如果未找到匹配元素则返回null。与之相对,getElementsByClassName根据类名查找,返回一个实时的HTMLCollection集合,该集合类似数组但并不是真正的数组,需要通过索引或循环访问每个元素。

现代浏览器还支持querySelectorquerySelectorAll,它们接受任意CSS选择器并分别返回第一个匹配元素和所有匹配元素的静态NodeList。使用CSS选择器可以更灵活地完成复杂查找,例如后代选择器、子代选择器、属性选择器等。以下代码展示了这几种方法的基本用法。

// 通过id获取单个元素
const container = document.getElementById('container');
if (container) {
    console.log('获取到的容器元素:', container);
}

// 通过类名获取元素集合
const items = document.getElementsByClassName('item');
for (let i = 0; i < items.length; i++) {
    console.log('第' + (i + 1) + '个item元素:', items[i]);
}

// 通过CSS选择器获取元素
const firstCard = document.querySelector('.card');
const links = document.querySelectorAll('p > a');
console.log('第一个卡片元素:', firstCard);
console.log('所有p标签下的a元素数量:', links.length);

需要注意的是,getElementsByClassName返回的HTMLCollection是动态集合,当文档结构发生变化时,集合内容会自动更新;而querySelectorAll返回的NodeList是静态集合,不会随文档变化。这一差异在遍历过程中会影响代码行为,应根据实际需求选择合适的查找方式。

三、修改元素内容、属性与样式

获取元素之后,最常见的操作就是修改元素的内容、属性和样式。修改内容可以通过innerHTMLinnerTexttextContent三个属性实现。它们虽然都能改变元素中的文本或结构,但行为存在明显区别。

属性行为说明
innerHTML获取或设置元素内部的HTML内容,包含标签,设置时会解析HTML标签。
innerText获取或设置元素内部的可视文本,忽略HTML标签,结果受CSS样式影响。
textContent获取或设置元素内部的所有文本内容,忽略HTML标签,不受CSS样式影响。

从上表可以看出,如果仅修改文本内容,推荐使用textContent,因为它不会触发HTML解析,性能更好且安全性更高。而innerHTML适合需要插入HTML结构的场景,但需要注意避免将用户输入未经处理直接赋值,否则可能引入安全风险。以下示例演示了内容修改和属性修改的典型用法。

const title = document.getElementById('title');

// 修改纯文本内容
title.textContent = '新的标题内容';

// 设置包含HTML标签的内容,<em>会被解析为斜体
title.innerHTML = '新的<em>标题</em>内容';

// 修改图片元素的属性
const img = document.querySelector('img');
img.src = 'https://ipipp.com/new-img.png';
img.alt = '新图片';

// 操作自定义属性
img.setAttribute('data-id', '1001');
const dataId = img.getAttribute('data-id');
console.log('自定义属性data-id的值:', dataId);

修改样式则主要依赖style属性。style对象对应元素的内联样式,通过设置style对象中的属性可以动态改变元素的展示效果。对于CSS中多单词属性名称,在JavaScript中需转换为驼峰命名,例如background-color应写为backgroundColorfont-size应写为fontSize。下面是一个简单的样式修改示例。

const box = document.getElementById('box');

// 修改背景色
box.style.backgroundColor = '#f0f0f0';

// 修改尺寸
box.style.width = '200px';
box.style.height = '200px';

// 修改边框样式
box.style.border = '1px solid #ccc';

四、动态创建、插入与替换节点

除了修改已有元素,DOM操作还支持在页面中动态创建、插入、删除和替换节点。创建元素节点使用document.createElement,创建文本节点使用document.createTextNode。创建完成后,新节点通常需要通过添加方法挂载到文档中才会显示。

添加节点的常用方法是appendChild,它会把指定节点追加到父元素的子节点列表末尾。如果需要将节点插入到某个子节点之前,则可以使用insertBefore。删除节点使用removeChild,替换节点使用replaceChild。以下代码演示了创建、添加、删除和替换的完整流程。

// 创建元素节点和文本节点
const newDiv = document.createElement('div');
const textNode = document.createTextNode('这是新添加的div元素');
newDiv.appendChild(textNode);
newDiv.className = 'new-item';

// 将新节点添加到父元素末尾
const parent = document.getElementById('parent');
parent.appendChild(newDiv);

// 创建参考节点,将新节点插入到参考节点之前
const referenceNode = document.getElementById('reference');
const anotherDiv = document.createElement('div');
anotherDiv.textContent = '插入到参考节点之前的元素';
parent.insertBefore(anotherDiv, referenceNode);

// 创建替换节点
const replaceDiv = document.createElement('div');
replaceDiv.textContent = '替换后的元素';

// 用replaceDiv替换anotherDiv
parent.replaceChild(replaceDiv, anotherDiv);

// 删除替换后的节点
parent.removeChild(replaceDiv);

在进行批量插入操作时,频繁调用appendChildinsertBefore会导致浏览器多次重排,从而影响页面性能。此时可以使用DocumentFragment作为临时容器,将新节点先添加到文档片段中,最后一次性将文档片段添加到目标父元素,从而减少DOM操作次数。

五、事件绑定与交互响应

DOM操作的最终目标是响应用户交互。JavaScript通过事件机制实现交互响应,常见的事件类型包括鼠标事件、键盘事件和表单事件。鼠标事件如click、mouseover、mouseout分别对应用户点击、鼠标移入和移出;键盘事件如keydown、keyup对应按键按下和抬起;表单事件如input、submit对应输入变化和表单提交。

绑定事件推荐使用addEventListener方法。与传统的onclick等属性相比,addEventListener支持为同一元素绑定多个同类型事件处理函数,并且不会覆盖之前已绑定的函数。此外,它还允许通过第三个参数控制事件捕获或冒泡阶段。以下示例展示了按钮点击事件的绑定方式。

const btn = document.getElementById('submitBtn');

// 绑定第一个点击事件
btn.addEventListener('click', function(event) {
    // 阻止默认行为,例如阻止表单提交后的页面跳转
    event.preventDefault();
    console.log('按钮被点击了');
    alert('提交成功');
});

// 绑定第二个点击事件,不会覆盖前一个
btn.addEventListener('click', function() {
    console.log('第二个点击事件处理函数');
});

对于动态创建的元素,直接在元素创建后绑定事件是可行的;但如果元素是后续异步加载的,可能需要使用事件委托,将事件绑定在静态父元素上,通过判断事件目标来执行逻辑。事件委托可以减少内存占用并简化代码

下面通过一个列表点击的例子来演示事件委托的具体用法。将点击事件绑定在列表容器上,通过 event.target 判断实际点击的元素,可以避免为每个列表项单独绑定事件。

const list = document.getElementById('itemList');

list.addEventListener('click', function(event) {
    const target = event.target;
    // 判断点击的是否是列表项
    if (target.tagName === 'LI') {
        console.log('点击了列表项:', target.textContent);
        target.classList.toggle('active');
    }
});

如果列表项内部还包含其他元素,比如链接、图标或文本节点,event.target 可能指向这些内部元素,而不是 li 本身。这时可以使用 closest 方法向上查找最近的匹配元素,从而准确获取列表项。

list.addEventListener('click', function(event) {
    const li = event.target.closest('li');
    if (li && list.contains(li)) {
        console.log('点击的列表项:', li.textContent);
        li.classList.toggle('active');
    }
});

事件委托除了减少事件监听器的数量,还能自动兼容动态添加的元素。因为事件绑定在父元素上,即使之后通过 JavaScript 新增了子元素,新元素同样会触发父元素上的事件处理函数,无需重新绑定。

有时需要阻止事件继续向上冒泡,避免触发父元素上的其他事件处理逻辑。比如在列表项中放置一个删除按钮,点击删除按钮时只执行删除操作,而不触发列表项本身的选中效果。此时可以调用 event.stopPropagation()

list.addEventListener('click', function(event) {
    const li = event.target.closest('li');
    if (li) {
        console.log('列表项被点击');
    }
});

// 动态创建的删除按钮也可以使用事件委托
list.addEventListener('click', function(event) {
    if (event.target.classList.contains('delete-btn')) {
        event.stopPropagation();
        const li = event.target.closest('li');
        if (li) {
            li.remove();
            console.log('列表项已删除');
        }
    }
});

在上面的代码中,同一个列表容器绑定了两个点击事件。点击删除按钮时,第一个事件处理函数会因为冒泡而触发,但第二个事件处理函数在检测到删除按钮后会阻止冒泡,避免第一个处理函数继续执行。不过由于两个监听器都绑定在同一个元素上,stopPropagation 并不能阻止同一元素上的其他监听器执行。如果需要阻止同一元素上的其他监听器,可以使用 event.stopImmediatePropagation()

六、表单事件与输入处理

表单事件是用户输入交互的核心。input 事件在输入框内容发生变化时实时触发,非常适合做即时校验、字符计数或搜索提示。change 事件在元素值改变并且失去焦点后触发,适用于下拉框选择或文件上传等场景。submit 事件在表单提交时触发,通常用于前端校验和异步提交数据。

下面是一个常见的表单校验示例,包含用户名实时提示和表单提交拦截。

const usernameInput = document.getElementById('username');
const feedback = document.getElementById('usernameFeedback');
const loginForm = document.getElementById('loginForm');

usernameInput.addEventListener('input', function(event) {
    const value = event.target.value;
    if (value.length < 3) {
        feedback.textContent = '用户名至少需要3个字符';
        feedback.style.color = 'red';
    } else {
        feedback.textContent = '用户名可用';
        feedback.style.color = 'green';
    }
});

loginForm.addEventListener('submit', function(event) {
    event.preventDefault();
    const username = usernameInput.value.trim();
    if (username === '') {
        alert('用户名不能为空');
        return;
    }
    console.log('提交表单,用户名:', username);
    // 实际项目中可使用fetch或XMLHttpRequest发送数据到服务器
});

键盘事件常用于快捷键操作、输入限制或实时搜索。例如按下回车键触发搜索、按下 Esc 键关闭弹窗等。keydown 事件在按键按下时触发,keyup 事件在按键松开时触发。通过 event.key 可以获取按键的字符串值,例如 'Enter''Escape' 等。

const searchInput = document.getElementById('searchInput');

searchInput.addEventListener('keydown', function(event) {
    if (event.key === 'Enter') {
        event.preventDefault();
        console.log('执行搜索:', searchInput.value);
        // 调用搜索函数
    }
    if (event.key === 'Escape') {
        searchInput.value = '';
        console.log('已清空搜索框');
    }
});

七、DOM操作性能优化

频繁的 DOM 读写操作会导致页面多次重排和重绘,影响性能。掌握一些实用的优化技巧,可以有效提升页面交互的流畅度。

首先,合并 DOM 操作。使用文档片段 DocumentFragment 或先拼接 HTML 字符串,最后一次插入到文档中,避免在循环中直接操作 DOM。其次,缓存 DOM 引用。需要多次使用同一个元素时,应该将其保存在变量中,而不是反复通过 document.getElementById 等方法查询。

// 不推荐的写法:多次查询同一个元素
document.getElementById('box').style.width = '100px';
document.getElementById('box').style.height = '100px';
document.getElementById('box').style.backgroundColor = 'red';

// 推荐的写法:缓存元素引用
const box = document.getElementById('box');
box.style.width = '100px';
box.style.height = '100px';
box.style.backgroundColor = 'red';

另外,尽量使用 CSS 类来控制样式,而不是逐个修改 style 属性。例如切换一个 active 类来改变元素外观,可以减少内联样式操作,也更有利于维护。

// 切换类名
const menu = document.getElementById('menu');
menu.classList.toggle('open');

对于需要频繁触发的事件,例如 scrollresize 或输入框的 input,可以使用节流(throttle)或防抖(debounce)技术来限制事件处理函数的执行频率。防抖通常用于搜索输入,用户停止输入一段时间后才发起请求;节流适用于滚动加载等场景,保证一定时间间隔内只执行一次。

// 简单防抖函数
function debounce(fn, delay) {
    let timer = null;
    return function(...args) {
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(this, args);
        }, delay);
    };
}

searchInput.addEventListener('input', debounce(function() {
    console.log('发起搜索请求:', searchInput.value);
}, 300));

八、总结

DOM 操作与事件绑定是前端开发的基础能力。通过合理选择 DOM 查询方法、掌握节点增删改查技巧、利用文档片段优化批量操作、理解事件冒泡与委托机制,能够编写出更高效、更易维护的代码。同时,结合实际场景运用表单事件、键盘事件以及性能优化策略,可以显著提升用户交互体验。

这些基础概念不仅在原生 JavaScript 开发中至关重要,也为理解现代前端框架如 React、Vue 的虚拟 DOM 与合成事件机制提供了底层支撑。希望本文的讲解和示例能够帮助你在实际项目中更加熟练地操作 DOM、处理用户交互,并写出性能更优的前端代码。

JavaScriptDOM前端开发DOM操作修改时间:2026-07-19 10:27:42

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。