前言
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 - 表单属性:
type、value、checked、selected、disabled等 - 注意 :
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;
注意 :previousElementSibling和nextElementSibling不支持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操作网页的能力。