入门魔法 - 针对 DOM 节点的简单操作

前情提要

上回说了希望选择学习火属性魔法後,艾草带我走到一棵大树下。

艾草:「来尝试用自己现有的魔力试试看能否选取到树上红色的果实。」

「呃啊啊啊...呼哈呼哈...魔力呀,听我号令,供我使唤...(下略一百字」

艾草:「就算把所有中二台词都说完了,也不会选比较快唷!别急,等选到了来教你怎麽改体内的元素。」

「我我好像感觉到了,体内一股热气,从胃部到喉咙,这难道就是魔力的感觉吗?」

艾草:「那是你的胃食道逆流啦(・⊝・) ,没关系,我从头教导你选取方法吧!」
https://ithelp.ithome.com.tw/upload/images/20210928/20139066M5VscAdu9s.png


DOM

DOM 的英文全名是:Document Object Model ,那它指的是什麽呢?

平常我们在写 HTML 的时候只会看到一堆程序码,但网页是如何解析我们撰写的这些程序码呢?

其实是透过 DOM tree 节点树状图的方式,如下:

https://ithelp.ithome.com.tw/upload/images/20210928/20139066XWQsrgmENp.png

DOM tree 是从 document 物件的根节点开始透过树状结构的方式,一路解析下来,而我们在操作网页元素时,可以去选取每个节点,并设定想要的操作,来达成想要的网页互动效果。

也因为浏览器解析 HTML 结构是由上往下解析的关系,所以当你把要载入的 JavaScript 档案放置於 head 时,却想操作 body 内的节点时,会无法操作!

因为当浏览器一解析到 JavaScript 档案,会跑去执行 JavaScript 档案,执行完成後就不再执行了,所以要记得摆放於 body 上方!

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <!-- JavaScript 档案载入放置处 -->
  <script src="all.js"></script>
</body>
</html>

DOM 操作方法

选取节点的方式有很多种,这边来介绍我最常使用到的 querySelector 方式!

querySelector

我们可以使用 querySelector 的方式选取想要的 Element ,而它会回传符合的第一个节点,querySelector 的选取方式是透过字串的形式,且是使用 CSS 选择器的方式选取。

HTML:

<h1 id="title" class="title"></h1>

JavaScript:

console.log(document.querySelector('h1'))//<h1 id="title" class="title"></h1>
console.log(document.querySelector('.title'))//<h1 id="title" class="title"></h1>
console.log(document.querySelector('#title')//<h1 id="title" class="title"></h1>

既然说了是透过 CSS 选择器的方式选取,当然以上三种方法都选的到 h1 Element ,如果想透过後代选择器方式选取也可以:

HTML:

<ul>
  <li></li>
</ul>

JavaScript:

console.log(document.querySelector('ul li'))//<li></li>

刚刚有提到 querySelector 是选取到第一个节点,那如果我们 Element 想一次选取多个可以怎麽做呢?

可以透过 querySelectorAll 的方式。

querySelectorAll

querySelectorAll 可以选取多个 Element ,并透过 nodeList 的方式回传给我们,如下:

HTML:

<a href="#">连结一</a>
<a href="#">连结二</a>
<a href="#">连结三</a>

JavaScript:

console.log(document.querySelectorAll('a'))//["<a/>","<a/>","<a/>"]

而该 nodeList 为类阵列物件,为何说是类阵列呢?

因为如果要读取其中的资料,是必须透过阵列方式去读取的。

HTML:

<a href="#">连结一</a>
<a href="#">连结二</a>
<a href="#">连结三</a>

JavaScript:

console.log(document.querySelectorAll('a')[0])//<a href="#">连结一</a>

另外 nodeList 也可以使用阵列方法 forEach 唷!

当我们选取到想要的 Element 後想在里面插入文字内容可以使用什麽方式呢?

textContent

textContent 可以让你在想要的节点 Node 插入文字 Text,请特别注意插入文字的地方指的是:
https://ithelp.ithome.com.tw/upload/images/20210928/20139066nE51MCzZHy.png

如果我想将某个 h1 Element 内的 Text 从"标题"改成"我是新标题",可以这样写:

HTML:

<h1>标题</h1>

JavaScript:

//透过 querySelector 选取 h1 Element 
let el = document.querySelector("h1");

//使用 textContent 替换文字内容
el.textContent = "我是新标题";

更改後的结果,就会显示我是新标题罗!

但要留意,使用这个方法会将原有的文字内容覆盖掉。

既然刚刚特别提到 textContent 是插入文字 Text ,那一定也有插入元素 Element 的方法,那就是 innerHTML

innerHTML

可以透过 innerHTML 来插入 element 元素。

例如想在列表元素 ul 内插入 li ,可以这样操作:

HTML:

<ul class="list">
  <li>我是原本就存在的 li </li>
</ul>

JavaScript:

//透过 querySelector 选取 class list 
let list = document.querySelector(".list");

//使用 innerHTML 插入 Element
list.innerHTML = "<li>我是新增的 li </li>";

显示後的结果:
https://ithelp.ithome.com.tw/upload/images/20210928/201390661LKfWyc8QU.png

因为 innerHTML 会将原有的内容覆盖掉,所以会只剩下"我是新增的 li"。

getAttribute

可以透过 getAttribute 来读取网页元素的属性,什麽是属性呢?

如 a 连结的 href 、 img 的 src 等,每个不同的 HTML 元素内都会有对应的属性,而我们可以使用 getAttribute 读取那些属性。

属性举例:

https://ithelp.ithome.com.tw/upload/images/20210928/20139066sgSJOZubjB.png

读取的方式如下:

HTML:

<a href="#"></a>

JavaScript:

console.log(document.querySelector('a').getAttribute("href"))//#

透过 getAttribute() 这个函式,并将属性用字串的方式当成参数填进去,就能成功读取出属性罗。

setAttribute

我们可以透过 setAttribute() 这个函式来新增或更改属性的值,它总共需要传入两个参数,分别为:

  • 想选取的属性
  • 想新增、修改的值

而需要透过字串形式的方式,两个参数间使用, 逗号区隔。

使用方式如下:

HTML:

<a href="#"></a>

JavaScript:

//透过 querySelector 选取 a
const link = document.querySelector("a");

// 透过 setAttribute 更改 href 属性的值为 "https://www.google.com.tw/"
link.setAttribute("href","https://www.google.com.tw/")

console.log(link)//<a href="https://www.google.com.tw/"></a>

总结

  • 网页解析 HTML 档案时会解析成 DOM tree 节点树状图
  • 载入 JavaScript 档案记得放置於 body
  • querySelector 可以选取第一个符合的 Element
  • querySelectorAll 可以选取多个符合的 Element ,并透过 nodeList 回传
  • textContent 可以插入文字 Text 内容
  • innerHTML 可以插入 element 元素
  • getAttribute() 可以读取网页元素的属性
  • setAttribute() 可以更改网页元素的属性值,可以传入两个参数:
    • 想选取的属性
    • 想新增、修改的值

小练习

请问以下叙述何者错误?
A 网页解析 HTML 时会透过 DOM tree 节点树状图的方式
B querySelectorquerySelectorAll 都可以选取 element 元素,差别在 querySelector 仅能选取第一个符合的
C 如果想读取元素属性,可以透过 getAttribute() 、想修改元素属性,可以透过 setAttribute()
D 透过 innerHTML 插入element 元素时,不会覆盖原本的element 元素,会透过新增的方式插入element 元素

解答: D 错误,使用 innerHTMLtextContent 皆会覆盖掉原本的内容


参考文献

JavaScript 必修篇 - 前端修练全攻略(六角学院)


<<:  Day28. Rails 搭配 DataTable 写出完美的列表页

>>:  Day13 用python写UI-聊聊Frame

Day 12. slate × Interfaces × Data-Model

上一篇我们有提到上图这些画了黄框的 files ,是我们在建立 editor 与操作 editor...

Day_26 vsftpd

今天介绍另外一个古老的文件技术FTP(File Transfer Protocol)。建立一个档案s...

[day-3] 一切的开端,认识你所使用的工具,Visual Studio Code !(Part .1)

何谓Visual Studio Code ?   Visual Studio Code(简称 VS ...

Day24-Kubernetes 那些事 - 内部架构

前言 之前的文章提到透过 K8s 的 Health Check,可以将不健康的 Pod 砍掉重建,或...

Day20 - 更新推文及冲突

今天来做更新推文的部分。 更新的部分实作上并没有太困难的地方,主要是处理冲突比较麻烦。 更新推文 更...