DOM API 一篇就会!
为什么需要学 DOM API?
当网页加载 HTML 文件时浏览器会生成 DOM,而开发者们可以借由 DOM API 让开发者可以程序化的操纵整个页面文件。由于 JavaScript 并不了解 HTML 的结构,因此浏览器生成出来的 DOM 就是 HTML 但用「对象」的方式作呈现。 简单来说,学习 DOM API 可以帮助我们使用 JavaScript 操纵网页上任何元素!
如果将 DOM 转换为图表理解,会以类似「树状关系图」的样貌展现,因此 DOM Tree 也代表 DOM 架构资料的图像化呈现,如下图:

什么是 DOM 节点?
名称 | 说明 |
---|---|
文档节点 | 代表整个文档的起点,所有节点的起源 |
元素节点 | 代表元素(Element),像是 <div> 、<script> 、<h1> |
属性节点 | 代表元素的属性如 id 、class |
文本节点 | 代表元素或属性内的纯文本内容,换行与空格也是一种文本节点。 |
注释节点 | 代表文档中的注释 |
任何东西在 HTML 文档中都是一种 DOM 节点,常见的节点可参考以上图表。节点是构成 DOM 的最基础的材料,了解有不同的节点可以更清楚的知道想选取的内容、选到的内容是什么、应该如何处理。在文章后头会认识到各种方法来选取这些不同种类的节点,进而程序化的操纵与监听它们来达成程序化控制网页的目的。
接下来将会分为三大章节,一步一步学习如何运用 JavaScript 通过 DOM API 操作网页,学会存取、编辑与监听 DOM。
一、选取 DOM 节点
HTML 的元素之间有辈分关系,这点也体现在 DOM 的结构上,可以依据一个节点来抓取不同关系的节点,举以下的代码为例:
<div> <h2>A List</h2> <ul> <li>List Item 01</li> <li>List Item 02</li> </ul></div>
对 <ul>
这个元素来说: <h2>
就是其同辈 <div>
就是其父母 <li>
就是其子孙。了解元素彼此间的关系之后,就可以运用不同的方法来选取网页中的节点。
实际常见范例
在大多数情境下其实不用记下太多的选取方法,只要记得常用的即可,像是选取单一元素的 qerySelector
以及选取多个元素的 querySelectorAll
就可以应付绝大多数约 90% 的情境。
<div id="foobar" class="foobar">Hello, World</div><ul> <li>Item 01</li> <li>Item 02</li> <li>Item 03</li></ul>
<script> // 依 document 为基准,选取符合 .foobar 选择器群组的元素 const foobar = document.querySelector('.foobar'); // 依 document 为基准,选取所有 ul 内的 li const foobar2 = document.querySelectorAll('ul li');</script>
更进阶的选取 DOM 节点
练习完不同选取 DOM 的方法之后,会发现不同的方法返回的结果会不太一样,这是因为它们所选取的「东西」不太相同,总共会遇上四种返回的结果。细节综合成以下清单与表单:
节点
构成 DOM 的基础组成,任何 DOM 中的东西都是结点。
元素
元素是一种节点,举例来说 <h1>
、<body>
、<div>
都是元素。
节点清单
节点的集合,一笔类似数组的数据,像是有索引和 forEach
方法。绝大多数时候是静态的,意味着 DOM 的改变并不会反映于资料上。
HTML 合集
元素的集合,一笔类似数组的数据,像是有索引。是动态的集合,意味着 DOM 的改变都会反映于资料上。
名称 | 元素 Element | 节点 Node |
---|---|---|
内容 | 只允许 HTML 元素(像是 <span> <div> 之类的标签) | 只允许任何存在于 HTML 文件中的节点(注释、内文字都算) |
方法与属性 | 一种特别的节点,拥有一些额外的属性 | 最基础的 HTML 组件,一些基础的属性 |
使用时机 | 绝大多数时候 | 选取 HTML 标签以外的事物时 |
名称 | HTML 合集 HTMLCollection | 节点清单 NodeList |
---|---|---|
说明 | 文件元素的合集 | 文件节点的合集 |
可使用的数组方法 | 无 | 仅有 forEach |
即时更新 | 是 | 大多不是 |
二、编辑 DOM 节点
当选取完 DOM 节点后让将结果打印出来,看看有哪些属性:
<div id="foobar">Hello</div>
<script> // 以 document 为基准,选取第一个 id 为 foobar 的元素并打印出来 console.log(document.getElementById('foobar'));</script>
得到类似以下动图中的打印结果:
可以发现每个元素对象身上都有许多的属性与方法可操作,看起来非常复杂,但常用的属性实际上并不多,在需要的时候再查阅文档了解即可。以下用两种最常被选取的属性种类作为范例来介绍(改样式与内容):
改变元素外表样式
要修改元素的外观样式可以从 class
属性与 style
属性下手,可以直接修改元素属性来达成更改样式的目的,举以下例子来说:
// 修改元素的 style 属性:element.style.backgroundColor = 'red';element.style.marginTop = '16px';element.style['padding-top'] = '16px';
// 修改元素的 style 属性:element.classList.add('active'); // 新增 "active" classelement.classList.remove('active'); // 移除 "active" classelement.classList.toggle('active'); // 切换 "active" class
改变元素内容
要修改元素的内容常见可以分为「修改 HTML」与「修改纯文字」,端看需求选择不同的方式,举以下例子来说:
// 修改选取元素的 HTML 内容document.getElementById('foobar').innerHTML = '<h1>This is some text</h1>';// 修改选取元素的文字内容document.getElementById('foobar').innerText = 'This is some text';
三、监听 DOM 节点
addEventListener 事件监听器
如果想要知道用户对网页做了哪些互动,就可以使用 addEventListener
方法来监听元素的活动,大多时候范例一、二就可以应对所有事件监听的要求。语法如下:
addEventListener(type, listener, options);
// 使用元素的 addEventListener 方法,当 "click" 时调用 clicked 函数// 以下三种写法都可行
// 范例一:调用外部函数element.addEventListener('click', clicked);function clicked() { // ...}
// 范例二:调用匿名函数element.addEventListener('click', function () { // ...});
// 范例三:添加设置对象:当激活过一次这个事件监听就会停止监听element.addEventListener('click', function () {}, { once: true });
removeEventListener 移除事件监听器
当不需要事件监听时可以手动删除来避免背景有太多事件监听导致影响性能,这项方法仅能删除以调用外部函数来执行的事件监听器,调用匿名函数的事件监听器是删不掉的。
// 添加监听element.addEventListener('mousemove', myFunction);
// 移除监听element.removeEventListener('mousemove', myFunction);
监听表单
当想要用户输入资料,就是 <form>
表单登场的地方,它提供了一系列基础的方法和接口让我们可以更方便快速且标准化的获取用户输入的资料,其中可使用 submit
事件监听获取提交的表单。
<form data-form> <input name="userInput" type="text"> // 设置 name 以便之后读取 <input type="submit"></form>
const form = document.querySelector('[data-form]');// 带入form.addEventListener('submit', (e) => { console.log(e.target.userInput.value); // 获取 name = "userInput" 的值 e.preventDefault(); // 取消默认事件(跳转页面) e.target.reset(); // 清空表单});
阻挡默认行为
在某些元素上会自带默认的「事件」,像是点击 <a>
或提交 <form>
都会跳转到其他页面,这时候就可以使用 preventDefault
来取消这些默认事件。此外在事件监听最尾端传入一个 false
也有同样阻挡默认行为的效果。
element.addEventListener('click', (e) => { e.preventDefault(); // 获取事件,阻挡默认行为发生});
总结
- DOM 是文件使用对象的方式做呈现,画成图表架构就像一棵树。
- HTML 文件中的任何信息在 DOM 中都是一种节点。
- 选取多个节点会返回 NodeList ,选取多个元素会返回 HTMLCollection,它们是类数组的对象。
- 节点有许多默认方法与属性,可以在终端打印出来后查询文档即可。
本篇是我在 六角学院 JS 直播班针对该主题所出的入门题目,内含解答,有兴趣可以点开来练习:JS 直播班 - 2022 秋季班 - DOM 操作