【前端教程】DOM 操作入门专栏:从基础到实战
DOM(文档对象模型)是 JavaScript 操作 HTML 页面的核心,掌握 DOM 操作能让你轻松实现页面的动态交互。本专栏将分三节课,从 DOM 结构、节点获取到节点创建与操作,带你逐步掌握 DOM 核心技能。
第一课:DOM 基础结构与核心节点概念
要操作 DOM,首先得理解其本质——DOM 将 HTML 文档转化为一个树形结构,每个 HTML 元素、属性、文本都对应一个“节点”,整个文档就是由这些节点组成的“节点树”。
一、核心概念:节点的分类
DOM 中的节点主要分为三类,后续所有操作都围绕这三类节点展开,必须能准确区分:
- 元素节点:HTML 标签本身,比如
<div>
、<p>
、<ul>
等,是页面结构的核心载体。 - 属性节点:标签的属性,比如
<div id="box" class="container">
中的id
、class
,用于描述元素的特征。 - 文本节点:标签内部的文字内容,比如
<p>Hello DOM</p>
中的“Hello DOM”,是页面的文本信息。
二、节点的三大核心属性
每个节点都有 nodeType
、nodeName
、nodeValue
三个属性,通过这三个属性可以快速判断节点类型,是 DOM 操作的“识别工具”,具体规则如下:
节点类型 | nodeType(固定值) | nodeName(节点名称) | nodeValue(节点值) |
---|---|---|---|
元素节点 | 1 | 大写的标签名(如 DIV、P) | null(元素节点无“值”概念) |
属性节点 | 2 | 小写的属性名(如 id、class) | 属性的具体值(如 box、red) |
文本节点 | 3 | 固定为 #text | 文本的具体内容(如 Hello) |
示例:以 <div id="box">Hello</div>
为例
- 元素节点(
<div>
):nodeType=1
,nodeName="DIV"
,nodeValue=null
- 属性节点(
id
):nodeType=2
,nodeName="id"
,nodeValue="box"
- 文本节点(“Hello”):
nodeType=3
,nodeName="#text"
,nodeValue="Hello"
第二课:DOM 节点获取的 4 种核心方式
获取节点是 DOM 操作的第一步——只有先“找到”节点,才能对其进行修改、删除等操作。常用的获取方式有 4 种,分别对应不同的属性维度,需注意返回结果的差异(单个节点 vs 节点数组)。
一、按 id 获取:getElementById()
- 原理:根据 HTML 标签的
id
属性获取节点,id
在页面中是唯一的(规范要求),因此只会返回单个节点。 - 语法:
document.getElementById("id属性值")
- 特点:最简单、直接的方式,获取速度快,返回结果是“单个节点”(不是数组),若未找到则返回
null
。 - 示例:
<div id="box">我是id为box的元素</div> <script>// 获取id为box的节点const box = document.getElementById("box");console.log(box); // 输出 <div id="box">...</div> </script>
二、按 class 获取:getElementsByClassName()
- 原理:根据 HTML 标签的
class
属性获取节点,class
可重复(多个标签可共用一个 class),因此返回节点数组(HTMLCollection)。 - 语法:
document.getElementsByClassName("class属性值")
- 特点:返回的是“类数组”(可通过索引访问,如
arr[0]
),若未找到则返回空数组。 - 示例:
<p class="text">文本1</p> <p class="text">文本2</p> <script>// 获取所有class为text的节点const textNodes = document.getElementsByClassName("text");console.log(textNodes[0]); // 输出第一个 <p class="text">文本1</p> </script>
三、按 name 获取:getElementsByName()
- 原理:根据 HTML 标签的
name
属性获取节点,name
常用于表单元素(如<input>
),可重复,返回节点数组(NodeList)。 - 语法:
document.getElementsByName("name属性值")
- 特点:主要用于表单场景,返回“类数组”,若未找到则返回空数组。
- 示例:
<input type="radio" name="gender" value="male"> 男 <input type="radio" name="gender" value="female"> 女 <script>// 获取所有name为gender的单选框const genderNodes = document.getElementsByName("gender");console.log(genderNodes.length); // 输出 2 </script>
四、按标签名获取:getElementsByTagName()
- 原理:根据 HTML 标签的名称(如
div
、p
、ul
)获取节点,标签名可重复,返回节点数组(HTMLCollection)。 - 语法:
document.getElementsByTagName("标签名")
- 特点:可获取页面中某类标签的所有节点,返回“类数组”,若未找到则返回空数组;若传入
"*"
,可获取页面所有元素节点。 - 示例:
<ul><li>列表项1</li><li>列表项2</li> </ul> <script>// 获取所有li标签节点const liNodes = document.getElementsByTagName("li");console.log(liNodes[1]); // 输出 <li>列表项2</li> </script>
补充:获取节点的“亲属关系”
除了直接获取节点,还可通过“亲属关系”(父、子、兄弟)获取节点,常用于嵌套结构中:
关系类型 | 方法/属性 | 特点(是否包含文本节点) |
---|---|---|
子节点 | childNodes | 包含文本节点(如空格、换行) |
子节点 | children | 只包含元素节点(常用) |
第一个子节点 | firstChild | 包含文本节点 |
第一个元素子节点 | firstElementChild | 只包含元素节点(常用) |
最后一个子节点 | lastChild | 包含文本节点 |
最后一个元素子节点 | lastElementChild | 只包含元素节点(常用) |
父节点 | parentNode | 只返回当前节点的直接父元素节点 |
上一个兄弟节点 | previousSibling | 包含文本节点 |
上一个兄弟元素节点 | previousElementSibling | 只包含元素节点(常用) |
下一个兄弟节点 | nextSibling | 包含文本节点 |
下一个兄弟元素节点 | nextElementSibling | 只包含元素节点(常用) |
第三课:DOM 节点的创建、追加、删除与替换
掌握节点的“增删改”,就能实现页面的动态更新(如点击按钮添加列表项、删除内容等)。核心操作围绕“元素节点”“文本节点”“属性节点”展开。
一、创建节点:3 类节点的创建方法
1. 创建元素节点:createElement()
- 作用:创建一个新的 HTML 标签(元素节点)。
- 语法:
document.createElement("标签名")
- 示例:创建一个
<div>
元素节点// 创建div元素节点 const newDiv = document.createElement("div");
2. 创建文本节点:createTextNode()
- 作用:创建一个新的文本节点(用于填充元素节点的内容)。
- 语法:
document.createTextNode("文本内容")
- 示例:创建“新文本内容”的文本节点
// 创建文本节点 const newText = document.createTextNode("新文本内容");
3. 创建属性节点:setAttribute()
- 作用:给已创建的元素节点添加属性(本质是为元素节点关联属性节点)。
- 语法:
元素节点.setAttribute("属性名", "属性值")
- 示例:给上面创建的
newDiv
添加id
和class
属性// 给newDiv添加id和class属性 newDiv.setAttribute("id", "new-box"); newDiv.setAttribute("class", "new-container");
二、追加节点:将创建的节点插入页面
创建节点后,节点仅存在于内存中,需通过“追加”操作插入到 DOM 树(页面)中,常用两种方式:
1. 追加到子节点末尾:appendChild()
- 作用:将节点 A 追加到节点 B 的所有子节点末尾,成为 B 的最后一个子节点。
- 语法:
父节点.appendChild(要追加的子节点)
- 示例:将
newText
插入newDiv
,再将newDiv
插入页面的<body>
// 1. 将文本节点newText插入newDiv(newDiv成为父节点) newDiv.appendChild(newText); // 2. 将newDiv插入页面的body(body成为父节点) document.body.appendChild(newDiv);
2. 追加到指定节点前方:insertBefore()
- 作用:将节点 A 插入到节点 B 的前方,成为 B 的前一个兄弟节点。
- 语法:
父节点.insertBefore(要插入的节点, 目标节点)
- 示例:在页面中已有
oldDiv
之前插入newDiv
<div id="oldDiv">旧元素</div> <script>const oldDiv = document.getElementById("oldDiv");// 将newDiv插入到oldDiv前方(父节点是body)document.body.insertBefore(newDiv, oldDiv); </script>
三、删除节点:removeChild()
- 作用:删除父节点下的某个子节点(必须通过父节点删除,不能直接删除子节点)。
- 语法:
父节点.removeChild(要删除的子节点)
- 示例:删除页面中的
oldDiv
// 获取oldDiv的父节点(body),再删除oldDiv const parent = oldDiv.parentNode; parent.removeChild(oldDiv);
四、替换节点:replaceChild()
- 作用:用节点 A 替换父节点下的节点 B,替换后 B 会从 DOM 树中移除。
- 语法:
父节点.replaceChild(用于替换的节点, 被替换的节点)
- 示例:用
newDiv
替换oldDiv
// 用newDiv替换oldDiv(父节点是body) document.body.replaceChild(newDiv, oldDiv);