Skip to content

2-1DOM及相关案例(一) ​

本页对应 第二章WebAPIs,共 5 段视频,约 46 分钟。

学习目标 ​

  • 能用自己的话说明 API 的含义,并举例说明开发者只需调用浏览器提供的接口即可实现功能。
  • 能解释 DOM 的核心思想,说明 DOM 如何把页面元素解析为对象,并通过修改对象属性影响页面标签。
  • 能说明 document 是 DOM 的顶级对象和网页入口,并判断哪些操作需要以 document 开头。
  • 能使用 document.querySelector() 按 CSS 选择器获取第一个匹配元素,并正确处理返回对象或 null 的情况。
  • 能使用 document.querySelectorAll() 获取所有匹配元素,并区分它与 querySelector() 在返回结果上的差异。
  • 能判断伪数组的特征,使用 length 和索引遍历伪数组获取元素,并说明伪数组不能直接使用 push 等数组方法。

知识点 ​

Web APIs 能做什么 ​

为什么需要:学完 JS 基础后,我们还需要让 JS 真正操作页面,做出轮播图、选项卡、表单验证等效果。
怎么想:Web APIs 的作用就是让 JavaScript 去操作页面文档和浏览器。其中 DOM 负责操作页面文档,BOM 负责操作浏览器。
怎么做:先建立整体地图:DOM 学“找元素、改内容、改样式、做事件、节点操作”,BOM 学“操作浏览器、本地存储”等。
易错点:不要把 DOM 和 BOM 混为一谈;DOM 面向页面文档,BOM 面向浏览器。

API 与接口:先会用,再查文档 ​

为什么需要:课程里反复出现 API,不理解它,就不知道为什么要查文档、为什么要记参数和返回值。
怎么想:API 是应用程序接口(Application Programming Interface)。接口的意思是:无需关心内部如何实现,程序员只需要调用,就可以方便地实现某些功能。转写稿用榨汁机举例:我们不用关心榨汁机内部原理,按一下开关就能榨橘子汁,这个开关就相当于接口/API。
怎么做:接口本质是对象,对象里包含属性和方法;这些接口由浏览器厂商实现,我们开发者只负责调用。例如以前用的 alert 就是浏览器提供的 API,我们不需要关心它内部怎么弹出警示框,只需要调用。学习 API 分两步:第一步理解它是干啥的、能解决什么需求;第二步查文档,看参数、返回值、注意事项。推荐 MDN,它是 JS 比较权威的网站。
易错点:不要把“会调用”误解成“要自己实现内部原理”;查文档时重点看参数类型、返回值和是否找不到元素。

DOM 的核心思想:把网页内容当对象 ​

为什么需要:只有理解 DOM 为什么能操作网页,后面获取元素、改内容才不会变成死记硬背。
怎么想:DOM 是 Document Object Model,文档对象模型。它的核心思想是把网页内容当做对象来处理:页面里的标签会被解析成 DOM 对象,对象里有属性,修改对象属性会反过来影响页面标签。
怎么做:例如页面里有一个 div,DOM 会把它解析成对象;对象里能拿到 id、innerHTML 等属性。转写稿在控制台用 $0 表示当前选中的元素,然后读取和修改对象属性来验证。
易错点:DOM 操作不是直接“改标签文字”这么简单,而是通过 DOM 对象间接影响页面;调试时可用 console.dir 看对象结构。

js
// 控制台中选中元素后,$0 表示当前元素对象
$0.innerHTML = '我是box'
$0.title = '鼠标经过显示的文字'

document 是入口 ​

为什么需要:页面内容都在文档里,操作页面必须有一个统一入口。
怎么想:document 是 DOM 提供的顶级对象,可以理解为网页入口;想在网页中操作内容,都要经过 document。
怎么做:后面很多 API 都以 document 开头,例如获取元素。以前写 document.write 向页面文档写内容,也说明它是以 document 这个对象开头的。
易错点:不要把 document 当成普通标签;它是 DOM 的顶级对象,提供访问和操作网页内容的属性和方法。

获取元素:querySelector ​

为什么需要:想操作元素,第一步必须先获取元素。
怎么想:重点掌握通过 CSS 选择器获取 DOM 元素。querySelector 返回匹配指定 CSS 选择器的第一个元素对象。
怎么做:语法是 document.querySelector('CSS选择器')。参数必须是字符串,里面写 CSS 选择器;以前 CSS 怎么写,这里就怎么写。
易错点:参数忘记加引号;误以为能选多个,其实只选第一个;找不到时返回 null。

js
const box = document.querySelector('div')
console.log(box)
console.log(typeof box) // object

const secondLi = document.querySelector('li:nth-child(2)')
console.log(secondLi)

获取多个元素:querySelectorAll 与伪数组 ​

为什么需要:页面中常有多个 li,只获取第一个不够用。
怎么想:querySelectorAll 比 querySelector 多了 All,表示获取指定 CSS 选择器中的所有元素。
怎么做:语法是 document.querySelectorAll('CSS选择器'),返回伪数组,里面包含所有 DOM 对象。伪数组有长度、有索引号,但不能使用 push、pop 等真数组常用方法。可以用 for 循环遍历。
易错点:把 All 漏掉;以为返回真数组;以为页面只有一个元素时 querySelectorAll 就返回一个元素——它仍然返回伪数组,只是里面只有一个元素。

js
const lis = document.querySelectorAll('ol li')
console.log(lis)
console.log(lis.length)

for (let i = 0; i < lis.length; i++) {
  console.log(lis[i])
}

// lis.push(1) // 会报错:伪数组不能使用数组常用方法

今日内容与学习路径 ​

为什么需要:知道今天学什么,才能把零散 API 串起来。
怎么想:今天先学获取元素,再学操作元素内容、操作元素样式,最后学定时器中的间隔函数;综合案例是自动轮播图,每隔一段时间自动播放下一张,小圆点和文字也跟着变化。
怎么做:学习时按“获取元素 → 操作内容/样式 → 定时器 → 综合案例”推进。后续 7 天还会学事件基础、事件进阶、节点操作、BOM 与本地存储、正则表单验证和综合案例。
易错点:不要只背 API,要结合案例理解“获取对象后修改属性,从而影响页面”的链条;查文档时以 MDN 为主。

DOM 是什么 ​

为什么需要: 学完 JavaScript 基础后,我们要让页面“动起来”:改文字、换样式、做轮播图、响应用户点击。这些操作不能只靠写死的 HTML,而要通过浏览器提供的接口去操作网页文档。DOM 就是其中最重要的一组接口。

怎么想: DOM 的全称是 Document Object Model,即“文档对象模型”。它是 Web API 的一部分,由浏览器厂商实现,开发者只负责调用。你可以把它理解成“操作网页文档的开关”:我们不需要关心浏览器内部怎么实现,只要会用 DOM 提供的方法即可。注意,DOM 不是“盗墓/倒m”,也不是一门新语言;它是浏览器提供给 JavaScript 的对象模型。它和 BOM(浏览器对象模型)不同:DOM 管页面文档,BOM 管浏览器窗口等。

怎么做: 先记住三件事:DOM 用来操作网页文档;可以开发网页特效和用户交互;核心思想是把网页内容当对象处理。后续学习获取元素、修改内容、改样式,都是在使用 DOM 提供的属性和方法。

易错点: 不要把 DOM 和 BOM 混为一谈;不要把 DOM 当成“直接改 HTML 字符串”,它操作的是浏览器解析后生成的 DOM 对象;口述里的“dome、盗墓、倒m”都应统一写成 DOM。

DOM 的核心思想 ​

为什么需要: 如果每次改页面都去拼 HTML 字符串,既麻烦又容易出错。DOM 把标签解析成对象后,我们就可以像操作普通对象一样,通过属性和方法修改页面内容。

怎么想: DOM 的核心思想是:把网页内容当做对象来处理。比如页面里有一个 <div id="box">我是一个盒子</div>,DOM 会把这个标签解析成一个 DOM 对象。对象里会有 id、innerHTML 等属性。修改对象的属性,会反过来影响页面上的标签。这就是“文档对象模型”里“对象”两个字的含义。

DOM核心思想示意图

怎么做: 可以在浏览器控制台验证。右键检查页面,选中那个 div,Elements 面板后面会出现 $0,它表示当前选中的元素对象。在控制台输入 $0,能看到它对应 div#box;输入 $0.innerHTML,能读到“我是一个盒子”;再赋值修改它,页面文字会跟着变。还可以给对象加 title 属性,标签上会新增对应属性。调试代码类似:

js
$0.innerHTML = '我是box'
$0.title = '鼠标经过显示的文字'

这证明:DOM 先把标签解析成对象,再通过修改对象属性影响页面标签。

易错点: $0 只是开发者工具里的临时调试入口,正式代码不能直接依赖它;innerHTML 不要写成 inerHML;控制台改的是当前运行时的 DOM 对象,不是直接改源文件,正式效果要写进 JS 文件。

document 对象 ​

为什么需要: 页面里的元素都在文档中,操作网页内容需要一个统一入口。document 就是 DOM 提供的顶级对象,是访问和操作网页内容的入口。

怎么想: 可以把它理解为“网页文档的总入口”。DOM 里很多操作都以 document 开头,因为它代表整个文档。它提供的属性和方法,都是用来访问或操作网页内容的。

怎么做: 最直观的例子是向页面写内容:

js
document.write()

这里 document 是对象,write 是它提供的方法。后续获取元素也从它开始,例如 document.querySelector('div')。querySelector 的参数必须是字符串形式的 CSS 选择器,它只返回第一个匹配元素;如果找不到,返回 null。若要拿多个元素,用 querySelectorAll,它返回的是伪数组,哪怕只有一个元素也是伪数组。

易错点: document 是对象,不是标签;document.write() 是 DOM 提供的方法,实际开发中较少直接用来写页面;获取元素时别忘了给选择器加引号;不要把 querySelector 和 querySelectorAll 的返回值混为一谈:前者是一个元素对象或 null,后者是伪数组。伪数组有长度和索引号,但不能直接使用 push、pop 等数组方法。

课件图示 ​

课件第9页:Web APIs 课程安排 7天 第二天 DOM-事件基础 注册事件、tab栏切

课件第10页:Web APIs 课程安排 7天 第四天 DOM-节点操作 节点的增删改查 第五

课件第2页:DOM 文档对象模型 Web APIs BOM 浏览器对象模型 使用 JavaS

课件第11页:Web APIs 课程安排 7天 第七天 实战 小兔鲜个人实战

课件第18页:1. 什么是DOM l DOM(Document Object Model——文

课件第19页:1. 什么是DOM l document 对象 Ø 是 DOM 里提供的一个对象

课件第20页:总结 总结 1. DOM是什么?作用是什么? Ø 文档对象模型 Ø 操作网页文档

课件第24页:2.1 根据CSS选择器来获取DOM元素 (重点) 1. 选择匹配的第一个元素

代码示例 ​

示例一:document.querySelector 获取第一个元素 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>querySelector 获取第一个元素</title>
  <style>
    .box {
      width: 200px;
      height: 100px;
      background-color: pink;
    }
  </style>
</head>
<body>
  <div class="box">我是一个盒子</div>

  <ol>
    <li>小丽1</li>
    <li>小丽2</li>
    <li>小丽3</li>
  </ol>

  <script>
    // 1. 标签选择器:CSS 怎么写,这里就怎么写
    const box = document.querySelector('div')
    console.log(box)          // 拿到的是元素本身
    console.log(typeof box)   // object —— DOM 把标签解析成了对象
    console.dir(box)          // 以对象形式展开,能看到 className 等属性

    // 2. 类选择器
    const box2 = document.querySelector('.box')
    console.log(box2)

    // 3. 后代选择器:只拿到第一个 li,不是三个
    const li = document.querySelector('ol li')
    console.log(li)

    // 4. 想拿第二个 li:直接用 CSS 的 nth-child
    const li2 = document.querySelector('ol li:nth-child(2)')
    console.log(li2)

    // 5. 页面中没有 p 标签,匹配不到返回 null
    const p = document.querySelector('p')
    console.log(p)            // null
  </script>
</body>
</html>

关键行与易错点

  • document 是 DOM 的顶级对象、网页内容的入口,所以获取元素的 API 都从 document. 点出来。
  • 参数必须是字符串(CSS 选择器),忘记加引号是最常见的错误。
  • 这个方法只返回第一个匹配的元素,即使写 ol li 也只有一个 li。
  • 返回值是 DOM 对象(typeof 为 object);console.log 打印元素,console.dir 打印对象及其属性。
  • 匹配不到返回 null,不是 undefined,后续操作前要留意。

示例二:document.querySelectorAll 获取多个元素与伪数组 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>querySelectorAll 获取多个元素</title>
</head>
<body>
  <ul class="nav">
    <li>小丽1</li>
    <li>小丽2</li>
    <li>小丽3</li>
  </ul>

  <div class="box">页面里唯一的盒子</div>

  <script>
    // 1. 拿到 .nav 里所有的 li
    const lis = document.querySelectorAll('.nav li')
    console.log(lis)          // 伪数组,形如 [li, li, li]

    // 2. 伪数组的两个特征:有 length、有索引号
    console.log(lis.length)   // 3
    console.log(lis[0])       // 第一个 li 对象
    console.log(lis[1])
    console.log(lis[2])

    // 3. 伪数组没有数组的常用方法,push 会报错
    // lis.push(1)            // 报错:lis.push is not a function

    // 4. 用 for 循环遍历伪数组,拿到每一个元素对象
    for (let i = 0; i < lis.length; i++) {
      console.log(lis[i])
    }

    // 5. 页面中只有一个元素,得到的依然是伪数组
    const box = document.querySelectorAll('.box')
    console.log(box)          // 伪数组,里面只有一个元素
    console.log(box.length)   // 1
  </script>
</body>
</html>

关键行与易错点

  • 方法名别把 all 漏掉,写成 querySelector 就只能拿到一个元素。
  • 返回值是伪数组:有 length、有索引号,但没有 push / pop / splice 等数组方法,用了会报错。
  • 遍历伪数组用 for 循环(length + 索引)。
  • 即使页面中只有一个匹配元素,querySelectorAll 返回的也是伪数组(长度为 1),不是元素本身。
  • 参数同样是字符串形式的 CSS 选择器,引号不能少。

示例三:DOM 核心思想与 document 对象 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>DOM 核心思想:操作对象就是操作标签</title>
</head>
<body>
  <div id="box">我是一个盒子</div>

  <script>
    // 1. document 是 DOM 的顶级对象,是网页内容的入口
    document.write('我是 document.write 写进来的文字')

    // 2. 先获取元素,得到一个 DOM 对象
    const box = document.querySelector('#box')

    // 3. 读取对象的属性
    console.log(box.innerHTML)   // 我是一个盒子

    // 4. 修改对象的属性,页面上的标签跟着一起变
    box.innerHTML = '我是 box'

    // 5. 给对象加一个原来没有的属性,标签上也会生成对应属性
    box.title = '鼠标经过显示的文字'
    console.log(box.title)
  </script>
</body>
</html>

关键行与易错点

  • DOM 的核心思想:把网页内容当对象处理 —— 先把标签解析成 DOM 对象,再改对象的属性,标签就跟着变。
  • innerHTML 用来读写标签内部的内容;赋值时是整体替换,原来的文字会消失。
  • title 对应标签的 title 属性,鼠标经过时会显示提示文字。
  • document 是 DOM 的顶级对象和入口,document.write 这类方法都以 document 开头,原因就是写内容也要经过这个入口。
  • 验证技巧:在浏览器控制台选中元素后可用 $0 代表当前元素,先在控制台验证再回到编辑器写代码。

常见错误 ​

  1. 现象: 想改页面上所有 .item 的文本,写了 list.innerHTML = '...',页面毫无反应,或者只改了第一处。 原因: querySelectorAll 返回的是伪数组,伪数组本身没有 innerHTML、style 这类元素属性,你是在给一个“容器”赋值,不是在给元素赋值。 修法: 先用 for 循环取出 list[i],再对每个元素对象操作;心里默念“伪数组不能直接当元素用”。

  2. 现象: list.push(...) 报 push is not a function,或者 list.sort()、list.splice() 一调用就崩。 原因: 把伪数组当成真数组。伪数组只有 length 和索引,没有数组原型上的方法。 修法: 需要数组方法时先转换:Array.from(list) 或 [...list];只是遍历则直接用 for 循环即可,不必转换。

  3. 现象: 控制台报 xxx is not defined,位置就在 querySelector 的括号里。 原因: 参数忘了加引号,document.querySelector(box) 被当成变量名去查找。 修法: 参数必须是字符串形式的 CSS 选择器,document.querySelector('.box')、document.querySelector('#box');写之前先确认引号和选择器符号(. / #)都在。

  4. 现象: document.querySelector('.box') 返回 null,后面一取属性就报 Cannot read properties of null。 原因: 两种情况——选择器写错(漏了 .、类名拼错),或者 <script> 写在目标元素之前,执行时元素还没被解析出来。 修法: 先 console.log 确认拿到的是不是元素;再把 <script> 放到 </body> 前,或用 DOMContentLoaded 包一层。养成“取到先打印、再操作”的习惯。

  5. 现象: 页面上明明只有一个 .box,用 querySelectorAll('.box') 拿到的却是个“数组”,直接 .style.color 改不动。 原因: 误以为“只有一个匹配项时 querySelectorAll 会退化成单个元素”。它永远返回伪数组,只是长度为 1。 修法: 只想要一个元素就用 querySelector;已经用了 All 就必须走 [0] 或循环,不要混用两种返回类型的心智模型。

  6. 现象: querySelectorAll('li') 想选第 2 个,写了 querySelectorAll('li')[2],结果拿到的是第 3 个;或者用 querySelector 想选最后一个却只能拿到第一个。 原因: 索引从 0 开始;而 querySelector 天生只返回第一个匹配项,不管你在选择器里怎么“想选最后一个”。 修法: 索引换算清楚(第 n 个 → [n-1]);要精确定位某个位置的元素,把定位交给 CSS 选择器本身,如 querySelector('li:nth-child(2)')。

练习 ​

  1. 选择器对照练习 页面上有 <ul class="nav"><li>…</li>×3</ul> 和 <div id="box">。分别写出获取以下目标的代码:① 第一个 li;② 全部 li;③ id 为 box 的元素;④ .nav 里的第 3 个 li。写完后用 console.log 和 console.dir 各验证一次。

  2. 判断返回类型 给定四行代码,先不运行,判断每行返回的是“元素对象 / 伪数组 / null”,并说明理由: document.querySelector('p')(页面无 p)、document.querySelectorAll('p')(页面无 p)、document.querySelectorAll('.nav li')、document.querySelector('.nav li:nth-child(2)')。运行后核对,把判断错的记下来。

  3. 批量改样式 页面有 5 个 .card。用 querySelectorAll 一次性取到,循环给每个卡片设置不同背景色(可用数组存颜色),并给第 2 张单独加一个边框。要求:不使用 querySelector 重复获取。

  4. 修 bug 下面代码想给所有 li 加点击后变红的文本,但有错误,请找出并改正(至少两处):

    js
    const lis = document.querySelector('.list li')
    lis.style.color = 'red'
    lis.forEach(item => item.style.color = 'red')

    改正后说明:为什么原来那两行“一行没效果、一行报错”。

  5. 伪数组验证 取一组元素后,依次验证:打印 length、打印 [0]、尝试 push、尝试 Array.from 后再 push。把每次的输出或报错记录下来,用一句话总结“伪数组能做什么、不能做什么”。

原视频对照 ​

#视频时长
1什么是API以及课程安排07:38
2今日内容01:49
3什么是DOM11:42
4获取第一个DOM元素querySelector方法14:58
5获取多个DOM元素querySelectorAll以及伪数组10:15

小结 ​

  1. 这一节所有 API 都属于“先查文档再写代码”的类型:拿到一个陌生方法,先问三件事——参数要什么类型、返回什么类型、找不到时返回什么。这三问答上了,代码基本就不会写错。
  2. 选择元素的两条路本质区别只有一句:一个给元素,一个给伪数组。后续所有“改样式、改内容”的代码形态,都由这个返回值类型决定——单元素直接点,多元素先循环。
  3. 参数是 CSS 选择器,意味着你已有的 CSS 选择器功底可以直接复用;选择器写得越精确,后面就越不需要用 JS 去做筛选。
  4. null 是排查 DOM 问题的第一信号:它几乎总指向“选择器写错”或“脚本执行太早”这两件事,先查这两处,不要急着怀疑 API。
  5. 伪数组是 DOM 与数组之间的“隔离带”:遍历用它自带的索引没问题,一旦想用数组方法就必须显式转换,不要指望它“看起来像数组就真能用”。
  6. 变量声明统一用 const:元素引用一旦获取就不会重新赋值,这既是习惯,也顺手挡住了“不小心把变量覆盖成别的类型”这类错误。
  7. 调试顺序建议固定为:先打印看拿到什么 → 再 console.dir 看对象结构 → 最后写操作逻辑。跳步直接写操作,是这一节 bug 的主要来源。