JavaScript DOM 基础入门
之前我们主要讨论了 JavaScript 的语法核心,即 ECMAScript 规范。现在,我们将深入探讨 JavaScript 的另一重要组成部分——DOM(文档对象模型)。DOM 是操作网页元素的 API,它允许我们通过脚本动态地访问和修改文档的内容、结构和样式。
什么是 DOM?
DOM 全称为 Document Object Model(文档对象模型)。它为 HTML 文档提供了一种结构化的表示方式,并定义了如何通过脚本来访问和操作文档结构。其根本目的是让 JavaScript 能够与 HTML 元素进行交互,并制定了一套标准规范。
DOM 的核心构成是节点(Node)。节点是构成 HTML 页面的最基本单元。网页中的任何部分,如 HTML 标签、属性、文本内容、注释乃至整个文档,都可以被视为一个节点。尽管都是节点,但它们的类型各不相同。常见的节点类型包括四种:
- 文档节点:代表整个 HTML 文档。
- 元素节点:即 HTML 标签。
- 属性节点:元素的属性(如 class, id 等)。
- 文本节点:HTML 标签内的文本内容(包括标签间的空格和换行)。
不同类型的节点拥有不同的属性和方法。实际上,所有节点都是对象(Object)。当 HTML 加载完成时,渲染引擎会在内存中构建一棵 DOM 树,而诸如 getElementById 的方法就是从这棵树中获取元素节点。后续的修改操作实际上是在改变这些元素的属性。
DOM 的功能
利用 DOM,我们可以做什么?
- 查找元素节点:获取页面上的特定元素。
- 设置元素属性值:修改元素的 HTML 属性。
- 调整元素样式:动态改变元素的 CSS 样式。
- 动态创建与删除元素:在页面中添加或移除节点。
- 处理事件:响应用户操作(如点击、键盘输入等)。
获取 DOM 节点
要操作元素节点,首先必须找到它。以下三种方式是获取 DOM 节点的常用方法:
// 通过 id 获取单个元素节点(id 是唯一的)
var myDiv = document.getElementById("box1");
// 通过标签名获取元素节点数组(注意复数形式)
var divArray = document.getElementsByTagName("div");
// 通过 class 名称获取元素节点数组
var elementsWithClass = document.getElementsByClassName("hehe");
DOM 节点之间存在关联,我们可以通过节点间的相对关系来访问它们。这些关系以属性的形式存在:
| 父节点 | 兄弟节点 | 子节点 | 所有子节点 |
|---|---|---|---|
| parentNode | nextSibling nextElementSibling previousSibling previousElementSibling |
firstChild firstElementChild lastChild lastElementChild |
childNodes children |
var parent = node.parentNode; // 获取父节点
var nextBro = node.nextElementSibling || node.nextSibling; // 下一个兄弟节点
var prevBro = node.previousElementSibling || node.previousSibling; // 上一个兄弟节点
var sibling = node.parentNode.children[index]; // 通过父节点随意获取兄弟节点
var firstChildElement = node.firstElementChild || node.firstChild; // 第一个子元素节点
var lastChildElement = node.lastElementChild || node.lastChild; // 最后一个子元素节点
var allChild = parent.childNodes; // 获取所有子节点
操作 DOM 节点
前面介绍的是访问节点(属性),现在来学习操作节点(方法)。
创建节点
var newElement = document.createElement("tagName");
// 示例:
var listItem = document.createElement("li"); // 创建一个 li 标签
var customItem = document.createElement("adbc"); // 创建一个不存在的标签(可能无效)
console.log(listItem);
console.log(customItem);
console.log(typeof listItem);
console.log(typeof customItem);
插入节点
插入节点有两种方式:
// 方式一:追加到父节点的最后
parentNode.appendChild(newChildNode);
// 方式二:在参考节点前插入;如果参考节点为 null,则追加到最后
parentNode.insertBefore(newChildNode, referenceNode);
删除节点
// 用父节点删除子节点
parentNode.removeChild(childNode);
// 如果要删除自身
node.parentNode.removeChild(node);
复制节点
var clone = node.cloneNode(); // 浅克隆:只复制节点本身,不复制子节点
var deepClone = node.cloneNode(true); // 深克隆:同时复制所有子节点
操作节点属性
以如下图片元素为例:
<img src="images/1.jpg" class="img" title="hahah" alt="seeyou" id="a1">
获取属性
var img = document.getElementsByTagName("img")[0];
console.log(img.src); // 方式一:直接属性名
console.log(img["src"]); // 方式二:方括号
console.log(img.getAttribute("src")); // 方式三:getAttribute 方法
设置属性
img.src = "images/2.jpg"; // 直接赋值
img.className = "image2-box"; // 修改 class
img.setAttribute("title", "new title"); // 使用 setAttribute
删除属性
img.removeAttribute("class");
img.removeAttribute("id");
注意:innerHTML 和 innerText 的区别:
innerHTML:包含标签的完整内容。innerText(旧版火狐用textContent):仅文本内容,不包含标签。
还有 nodeType 属性:nodeType == 1 代表元素节点(标签),nodeType == 2 代表属性节点,nodeType == 3 代表文本节点。
style 属性
通过 style 属性只能操作行内样式,无法读取内嵌或外链样式。格式如下:
element.style.styleName; // 获取样式值
element.style["propertyName"]; // 方括号形式
element.style.propertyName = value; // 设置样式
注意事项:
- 适用于样式较少的情况。
- style 是对象,值是字符串。
- 命名采用驼峰规则(如
backgroundColor而非background-color)。 box.style.cssText = "样式字符串"可批量设置。
事件基础
事件是文档或浏览器中发生的特定交互瞬间,JavaScript 以事件驱动为核心。事件三要素:
- 事件源:触发事件的 HTML 元素。
- 事件:预定义的交互动作(如点击、悬停)。
- 事件驱动程序:执行 DOM 操作的代码。
基本写法:
// 1. 获取事件源
var btn = document.getElementById("target1");
// 2. 绑定事件
btn.onclick = function() {
// 3. 事件驱动程序
alert("事件被触发了!");
};
常见事件一览:
| 事件名 | 触发时机 |
|---|---|
| onclick | 鼠标点击 |
| ondblclick | 鼠标双击 |
| onkeyup | 按键松开 |
| onchange | 内容变化(如文本框、下拉菜单) |
| onfocus | 获得焦点 |
| onblur | 失去焦点 |
| onmouseover | 鼠标悬停 |
| onmouseout | 鼠标移出 |
| onload | 页面加载完成 |
| onunload | 页面关闭 |
| onsubmit | 表单提交 |
| onreset | 表单重置 |
绑定事件的方式
直接绑定
var btn = document.getElementById("target1");
btn.onclick = function() {
alert("直接绑定方式");
};
// 或者引用函数名(注意不加括号)
btn.onclick = myHandler;
function myHandler() {
alert("函数引用方式");
}
行内绑定
<button id="target1" type="submit" onclick="showAlert()">点击我</button>
<script>
function showAlert() {
alert("行内绑定调用函数");
}
</script>