JS DOM与事件处理完全指南

前言

DOM(文档对象模型)是JavaScript操作网页的核心接口。本文系统讲解DOM的基础概念、元素获取的五种方法、节点间的父子兄弟关系、事件处理的三种绑定方式以及元素内容和属性的操作方法。掌握这些内容,你就能随心所欲地操控网页内容和样式。


一、DOM基础概念

1.1 什么是DOM

DOM(Document Object Model) :文档对象模型,是一系列编程接口。通过这些接口可以改变页面的内容结构样式

1.2 DOM核心概念

术语 含义 DOM中表示
文档 一个页面就是一个文档 document
元素 页面中的所有标签都是元素 element
节点 网页中的所有内容(标签、属性、文本、注释等) node

DOM把以上内容都看作是对象,我们可以通过JavaScript对这些对象进行操作。


二、JavaScript加载时机

2.1 加载问题

浏览器按照自上向下 的顺序加载页面。如果将<script>标签写在页面顶部,此时DOM对象可能还未加载,导致无法获取元素。

2.2 解决方案

方案一:将script放在页面底部

将JS代码编写到页面的下部,确保页面加载完毕后再执行JS代码。

方案二:使用window.onload事件(推荐)

复制代码
window.onload = function() {
    // 此处可以安全操作DOM
    // 整个页面加载完成后才会触发
};

onload事件会在整个页面加载完成之后才触发,为window绑定一个onload事件,该事件对应的响应函数将会在页面加载完成之后执行,这样可以确保我们的代码执行时所有的DOM对象已经加载完毕了。


三、DOM元素获取方法

DOM在实际开发中主要用来操作元素。以下是获取DOM元素的常用方法:

3.1 基本获取方法

getElementById() --- 通过ID获取

通过id属性获取一个元素节点对象。

复制代码
let element = document.getElementById("elementId");

参数:id是大小写敏感的字符串

返回值:一个元素对象

补充说明

  • innerHTML:可读写,获取元素内部的HTML代码(包括标签),保留空格和换行,比较常用
  • innerText:可读写,获取元素内部的文本内容,会自动去除HTML标签、空格和换行
  • console.dir():打印返回的元素对象,可以更好地查看里面的属性和方法
getElementsByTagName() --- 通过标签名获取

根据标签名获取一组元素节点对象。

复制代码
let elements = document.getElementsByTagName("tagName");

特点

  • 返回一个**类数组(伪数组)**对象
  • 即使查询到的元素只有一个,也会封装到伪数组中返回
  • 如果页面中没有这个元素,返回一个空的伪数组

获取父元素内部指定标签

复制代码
let childElements = parentElement.getElementsByTagName("tagName");

注意:父元素必须是单个对象(必须指明是哪一个元素对象),获取的时候不包括父元素自己。

getElementsByName() --- 通过name属性获取
复制代码
let elements = document.getElementsByName("nameValue");

补充

  • innerHTML对于自结束标签(如<input>)没有意义
  • 读取元素属性语法:元素.属性名,例如:元素.id元素.name元素.src元素.href
  • 表单属性:typevaluecheckedselecteddisabled
  • 注意class属性不能采用这种方式,读取class属性时需要使用元素.className
  • value值:输入文本框中的内容,要修改value值使用element.value = "新值"
getElementsByClassName() --- 通过class属性获取
复制代码
let elements = document.getElementsByClassName("className");

注意:不支持IE8及以下浏览器。

3.2 现代获取方法(推荐)

document.querySelector()

需要一个选择器的字符串作为参数,根据一个CSS选择器来查询一个元素节点对象。

复制代码
let element = document.querySelector("selector");

特点

  • 总会返回唯一的元素
  • 如果满足条件的元素有多个,只会返回第一个
  • IE8及以上都适用
document.querySelectorAll()
复制代码
let elements = document.querySelectorAll("selector");

特点

  • 将符合条件的所有元素封装到一个伪数组中返回
  • 即使符合条件的元素只有一个,也会返回数组

3.3 特殊元素获取

复制代码
// 获取body元素
let body = document.body;

// 获取html根元素
let html = document.documentElement;

// 获取页面所有元素
let allElements = document.all;
// 或
let allElements = document.getElementsByTagName("*");

3.4 方法汇总

方法 返回值 说明
getElementById() 单个元素 通过id获取
getElementsByTagName() 伪数组 通过标签名获取
getElementsByName() 伪数组 通过name属性获取
getElementsByClassName() 伪数组 通过class获取(IE8-不支持)
querySelector() 单个元素 CSS选择器,返回第一个匹配
querySelectorAll() 伪数组 CSS选择器,返回所有匹配

四、DOM节点关系

4.1 父子节点关系

childNodes 与 children
复制代码
// 获取所有子节点(包括文本节点)
let allChildren = element.childNodes;

// 获取所有子元素节点(不包括文本节点)
let childElements = element.children;

区别

  • childNodes:获取包括文本节点在内的所有节点,标签间的空白也会被当成文本节点
  • children:获取当前元素的所有子元素,不包括空白文本节点
firstChild / firstElementChild 与 lastChild / lastElementChild
复制代码
// 第一个子节点(包括空白文本节点)
let firstChild = element.firstChild;

// 第一个子元素节点
let firstElementChild = element.firstElementChild;

// 最后一个子节点(包括空白文本节点)
let lastChild = element.lastChild;

// 最后一个子元素节点
let lastElementChild = element.lastElementChild;
parentNode --- 获取父节点
复制代码
let parent = element.parentNode;

4.2 兄弟节点关系

复制代码
// 前一个兄弟节点(可能包含空白文本)
let previousSibling = element.previousSibling;

// 前一个兄弟元素节点
let previousElementSibling = element.previousElementSibling;

// 后一个兄弟节点(可能包含空白文本)
let nextSibling = element.nextSibling;

// 后一个兄弟元素节点
let nextElementSibling = element.nextElementSibling;

注意previousElementSiblingnextElementSibling不支持IE8及以下浏览器。

4.3 节点关系速查表

属性 含义 是否包含文本节点
childNodes 所有子节点
children 所有子元素
firstChild 第一个子节点
firstElementChild 第一个子元素
lastChild 最后一个子节点
lastElementChild 最后一个子元素
parentNode 父节点 ---
previousSibling 前一个兄弟节点
previousElementSibling 前一个兄弟元素
nextSibling 后一个兄弟节点
nextElementSibling 后一个兄弟元素

五、事件处理

事件:用户和浏览器之间的交互行为,比如点击按钮、鼠标移动、关闭窗口等。

5.1 事件三要素

要素 说明 示例
事件源 触发事件的元素 按钮、输入框
事件类型 如何触发 click、mouseover
事件处理程序 事件触发后执行的函数 回调函数

5.2 事件绑定方式

方式一:HTML属性中设置(不推荐)
复制代码
<button onclick="alert('哈喽')">按钮</button>

缺点:结构与行为耦合,不方便维护。

方式二:JavaScript绑定(推荐)
复制代码
// 1. 获取事件源
let btn = document.getElementById("btn");

// 2. 绑定事件处理函数
btn.onclick = function() {
    alert("hello");
};
方式三:addEventListener(更灵活)
复制代码
btn.addEventListener("click", function() {
    alert("hello");
});

优点:可以为同一个元素绑定多个相同类型的事件处理函数。

5.3 常见事件类型

鼠标事件
事件 说明
onclick 鼠标点击左键
onmouseover 鼠标经过
onmouseout 鼠标离开
onmouseenter 鼠标进入(不冒泡)
onmouseleave 鼠标离开(不冒泡)
onmousemove 鼠标移动
onmousewheel 鼠标滚轮
键盘事件
事件 说明
onkeydown 键盘按键按下
onkeyup 键盘按键松开
表单事件
事件 说明
onfocus 获得焦点
onblur 失去焦点
oninput 输入时触发(每次输入)
onchange 值改变时触发(失焦后值改变)
复选框和单选框
复制代码
// 复选框选中状态改变
checkbox.addEventListener("change", handler);

// 单选框点击
radio.addEventListener("click", handler);

六、DOM节点属性与内容操作

6.1 元素内容操作

innerHTML vs innerText
操作 innerHTML innerText
读取 获取元素内部HTML(含标签),保留空格和换行 只获取文本内容,去除标签、空格和换行
写入 识别HTML标签 不识别HTML标签,自动转义
复制代码
// 获取/设置元素内部的HTML代码
element.innerHTML = "<strong>新内容</strong>";

// 获取/设置元素的文本内容(自动去除HTML标签)
element.innerText = "文本内容";
nodeValue 与 textContent
复制代码
// 获取文本节点的值
element.nodeValue;

nodeValue是所有节点对象都具有的属性,返回值取决于节点类型:

节点类型 nodeValue返回值
元素节点 null
文本节点 文本内容
属性节点 属性的值
复制代码
// 返回元素及其所有后代的文本内容
element.textContent;

6.2 元素属性操作

复制代码
// 读取元素属性
element.id;           // id属性
element.name;         // name属性
element.value;        // value属性
element.className;    // class属性(注意:不是class)

// 修改元素属性
element.type = "text";  // 修改type属性

注意 :读取class属性时必须使用element.className,而不是element.class


七、注意事项

7.1 浏览器兼容性

方法 兼容性问题
getElementsByClassName() IE8及以下不支持
previousElementSibling IE8及以下不支持
nextElementSibling IE8及以下不支持

使用前需考虑项目的兼容性需求。

7.2 节点与元素的区别

概念 范围
节点 包含所有内容(元素、文本、注释等)
元素 仅指标签元素

7.3 空白文本节点

DOM标准中,标签间的空白也会被当作文本节点。使用children而非childNodes可避免空白文本节点问题。


总结

本文系统梳理了JavaScript DOM操作与事件处理的完整知识体系:

主题 核心要点
DOM基础 文档(document)、元素(element)、节点(node)三大概念
元素获取 五种基本方法 + querySelector/All现代方法
节点关系 父子关系(childNodes/children)、兄弟关系(sibling)
事件处理 三要素(源、类型、处理程序)、三种绑定方式
内容操作 innerHTML vs innerText、nodeValue、属性操作

掌握这些内容,你就具备了使用JavaScript操作网页的能力。

相关推荐
前端 贾公子16 分钟前
Linux云服务器安装与PostgreSQL安装
运维·服务器
严谨的麻辣烫17 分钟前
批量静态 IP 如何管理?用 Python 建立一个简单的 IP 资源监控方案
运维·服务器·网络·python·tcp/ip
智恒百亿23 分钟前
企业 AI 推理本地化部署:GPU 服务器选型技术分析(2026 年 8 月)
大数据·服务器·人工智能
恋猫de小郭25 分钟前
Firebase 如何让全球 Android 和 Flutter 开发者集体 Build Fail
android·前端·flutter
墨白曦煜26 分钟前
智能体架构范式总结(React、Plan-And-Solve、Reflection)
前端·react.js·前端框架
qq_4260039629 分钟前
多语言新增语种全量测试策略的测试范围
前端·javascript·python·自动化
frjc40 分钟前
Node.js 与 npm 极简安装教程
前端·npm·node.js
IMPYLH41 分钟前
HTML 的 <main> 元素
前端·html
深念Y44 分钟前
微服务抽取路线图:从胖单体到 ARM 集群
前端·arm开发·数据库·后端·微服务·云原生·架构