上一節(jié)焕阿,咱們整理了DOM系列中的第一篇,主要介紹瀏覽器與DOM相關(guān)的知識唇兑。從標題中我們可以看出來,今天所要學(xué)的東西包含兩個部分,第一部分是DOM樹,第二部分是遍歷DOM。如果你和我一樣對于DOM樹和遍歷DOM是初次接觸,那個人建議您花點時間好好看看這兩部分的知識罢杉。
DOM樹
眾所周之著洼,HTML文檔的主干就是標記(也就是大家熟悉的HTML標簽元素)绊困。
根據(jù)文檔對象模型(即:DOM)那先,每個HTML標簽事實上都是一個對象。嵌套的標簽被稱為之元素(或子標簽)。除此之外慎颗,標簽內(nèi)的文本也是一個對象锚国。而這些對象都可以使用JavaScript訪問。
那么啥是DOM樹呢翔怎?我們先來看看現(xiàn)實生活中的例子窃诉。想象一棵與所有世代有關(guān)系的家庭樹(大家熟知的族譜),其包括了:祖父母赤套、父母飘痛、孩子、兄弟姐妹等等容握。我們通常以等級的方式組織豪庭樹(族譜)宣脉。
上圖是一個家族族譜的圖。其中Tossico
剔氏、Akikazu
塑猖、Hitomi
和Takemi
是祖父母。而Toshiaki
和juliana
是父母谈跛。另外TK
羊苟、Yuji
、Bruno
和Kaio
是父母的孩子(其實也是我的兄弟姐妹們)感憾。
除了家族族譜之外蜡励,生活中還有另一個示例,那就是一個組織的結(jié)構(gòu)層次阻桅,比如:
而在HTML中凉倚,DOM其實也類似一棵樹的,它和前面所舉例的家族族譜嫂沉,組織機構(gòu)圖是類似的稽寒,HTML中DOM就是一棵樹。
DOM的一個示例
我們來看一個DOM的示例输瓜,比如下面這樣的一個HTML文檔:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<!DOCTYPE HTML> <html>
<head>
<title>About elks</title>
</head>
<body>
The truth about elks.
</body> </html>
</pre>
DOM將HMTML表示為標記的樹結(jié)構(gòu)(也就是大家所說的DOM樹)瓦胎,就如下面這樣的樣子:
在上面的圖中芬萍,你可以單擊元素的節(jié)點,它們的子節(jié)點可以展開或者收縮搔啊,如下圖所示:
HTML的標簽被稱為元素(element
)節(jié)點(或只是元素)柬祠。嵌套標簽成為一個子元素(也被稱為子)。因此负芋,對于一個HTML文檔而言漫蛔,<html>
是一個根節(jié)點(也被稱為根元素),然后<head>
和<body>
是<html>
的子元素。
元素內(nèi)的文本被稱這文本節(jié)點旧蛾,標記為#text
莽龟。文本節(jié)點僅包含一個字符串。它可能沒有子元素锨天,也就是說它永遠只是樹的葉子(沒有成為樹枝的可能)毯盈。
除此之外,要注意文本節(jié)點中的兩個特殊字符:
換行符:
?
(對應(yīng)JavaScript中的\n
)空白符:
?
空格和換行符是完全有效的字符病袄,它們形成文本節(jié)點并成為DOM的一部分搂赋。因此,例如在<head>
標簽之上的示例中益缠,在<title>
這前包含了一些空格脑奠,并且該文本成為一個#text
節(jié)點(它只包含一條換行符和一些空格)。
不過要注意的是幅慌,有兩個將會除外:
在
<head>
標簽之前的空格和換行符由于歷史原因?qū)⒈缓雎?/p>如果我們將一些東西放在
</body>
之后宋欺,那么它就會自動地移到</body>
的前面,正如HTML規(guī)范要求的一樣胰伍,所有內(nèi)容必須在</body>
中一樣齿诞。因此,在</body>
之后可能沒有空格
在其他情況之下喇辽,一切都很簡單掌挚。如果文檔中有空格(就像任何字符一樣)雨席,那么它們就會成為DOM中的文本節(jié)點菩咨,如果我們刪除它們,那么就不會有任何東西陡厘,也不再會有空格符或換行符的節(jié)點抽米。
比如下面這個示例:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<!DOCTYPE HTML><html><head><title>About elks</title></head><body>The truth about elks.</body></html>
</pre>
上面的HTML結(jié)構(gòu)對應(yīng)的DOM樹如下圖所示:
相比上面的截圖可以看出來,沒有了空格符和換行符的文本節(jié)點糙置。
通過上面的示例云茸,可能你對DOM樹有一定的了解了。但對一些一技術(shù)的定義估計還不是非常的了解谤饭,接下來花點時間來說一下DOM中的一些技術(shù)定義标捺。
DOM中的技術(shù)定義
DOM樹(tree
)是一個DOM節(jié)點(nodes
)的集合(拿到生活中來說懊纳,樹是稱為節(jié)瞇的實體集合)。而其中節(jié)點由邊(edges
)連接亡容。每個節(jié)點(node
)都包含一個值(value
)或數(shù)據(jù)(data
)嗤疯,它可能或有可能沒有子節(jié)點(child node
)。
tree
的first node
稱為root
節(jié)點闺兢。如果root
節(jié)點由另一個節(jié)點連接茂缚,則root
節(jié)點是父節(jié)點,連接的節(jié)點是子節(jié)點屋谭。
所有的樹節(jié)點(Tree nodes
)都被edges
連接在一起脚囊。它是樹(trees
)的重要組成部分,因為它管理節(jié)點(nodes
)之間的關(guān)系桐磁。
對于一棵樹而言悔耘,葉子(leaes
)是樹(tree
)上的最后一個節(jié)點(nodes
)。它們是沒有子節(jié)點我擂。就像真正的樹一樣淮逊,DOM也是有根(root
)、枝(Element
)和葉子(文本節(jié)點)扶踊。
除此之外泄鹏,其他還需要理解的重要概念是高度(height
)和深度(depth
)。樹的高度是葉子最長路徑的長度秧耗;節(jié)點的深度是路徑到其根的長度备籽。用下圖來闡述會更形象一些:
簡單的總結(jié)一些術(shù)語:
root
(根節(jié)點)是樹(tree
)最頂端的節(jié)點edge
(邊緣)是兩個節(jié)點(node
)之間的連接child
(子節(jié)點)是具有父節(jié)點的節(jié)點parent
(父節(jié)點)是一個節(jié)點,它具有子節(jié)點的邊緣leaf
(樹葉)是樹中沒有子節(jié)點的節(jié)點height
(高度)是葉子最長路徑的長度depth
(深度)是路徑到其根的長度
有關(guān)于這方面更深入的介紹可以閱讀@TK的《Everything you need to know about tree data structures》一文分井。
另外@TK的文章還涉及到了深度優(yōu)先遍歷和廣度優(yōu)秀遍歷车猬,有關(guān)于這兩個概念的深入介紹,可以閱讀:
querySelectorAll
和getElementsByTagName
Demystifying Depth-First Search
Breaking Down Breadth-First Search
其實有關(guān)于深度優(yōu)先遍歷和廣度優(yōu)秀遍歷在DOM樹中的作用并不明顯尺锚,對于后續(xù)的DOM遍歷還是有很大的影響珠闰。
經(jīng)過的上面的學(xué)習(xí),我們對于DOM樹有了一定的了解瘫辩。除此之外伏嗜,瀏覽器對于DOM還具有自動較正的特性。
自動校正
如果瀏覽器遇到格式錯誤的HTML伐厌,它會自動更正它(校正)承绸。
例如,HTML最頂端的標簽總是<html>
挣轨。即使它不存在文檔中 —— 它將存在DOM中军熏,瀏覽器也會創(chuàng)建它。另外<body>
也是一樣卷扮。
例如荡澎,HTML文件只包含一個單詞Hello
均践,瀏覽器將它放置在成<html>
和<body>
中,并且也會添加所需的<head>
摩幔。其DOM將是:
另外浊猾,生成DOM時,瀏覽器會自動處理文檔中的錯誤热鞍,比如關(guān)閉標簽等等葫慎。比如下面這樣一個無效的文檔:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<p>Hello<li>Mom<li>and<li>Dad
</pre>
事實上,瀏覽器渲染時薇宠,它照樣會成為一個正常的 DOM偷办,那是因為瀏覽器讀取標簽并會自動修復(fù)丟失的部分(比如說關(guān)閉標簽):
除此之外,還有一個有趣的“特殊情況”澄港,那就是table
(表格元素)椒涯。根據(jù)DOM規(guī)范,它必須有<tbody>
回梧,但是如果你在HTML文檔中忘記寫該標簽元素時废岂,瀏覽器會自動在DOM中添加<tbody>
標簽。比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<table id="table"><tr><td>1</td></tr></table>
</pre>
此時瀏覽器渲染出來的DOM結(jié)構(gòu)如下:
其他節(jié)點類型
我們可以在一個HTML文檔中添加更多的標簽和在頁面中添加注釋狱意,比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<!DOCTYPE HTML> <html>
<body>
The truth about elks.
<ol>
<li>An elk is a smart</li>
<li>...and cunning animal!</li>
</ol>
</body> </html>
</pre>
對于上面的HTML文檔湖苞,其對應(yīng)的DOM樹如下圖所示:
上圖中,我們看到了一個新的節(jié)點類型 —— 注釋節(jié)點详囤,標記為 #comment
财骨。
你可能會想,為什么要將注釋添加到DOM中呢藏姐?它不會以任何方式影響視覺上的效果隆箩,但是有一個規(guī)則,如果某個東西在HTML中羔杨,那么它也必須在DOM樹中捌臊。
HTML中的一切,甚至是注釋兜材,都將成為DOM的一部分理澎。
即使是<!DOCTYPE ...>
指令也是一個DOM節(jié)點。它在DOM樹中护姆,在<html>
之前矾端。我們不會去觸摸那個節(jié)點,我們甚至不會在圖上畫它卵皂,但它卻實實大大的存在那里。
document
對象也是一個DOM節(jié)點砚亭,表示整個文檔灯变。在DOM中殴玛,其有12
種節(jié)點類型。在實際操作中添祸,我們通常使用4種方法:
document
:進入DOM的入口點元素節(jié)點:HTML標簽滚粟,樹構(gòu)建塊
文本節(jié)點:包含文本
注釋:有時候我們可以把信息放在這里,但它不會顯示出來刃泌,不過JavaScript卻可以從DOM中讀取它
或許你和我一樣凡壤,希望能對每個HTML文檔對應(yīng)的DOM結(jié)構(gòu)能實時的查看,我們希望有對應(yīng)的工具能幫助我們耙替。事實上是有類似這樣的工具亚侠,比如 Live DOM Viewer。只要輸入文檔俗扇,它就會立即顯示DOM樹結(jié)構(gòu)硝烂。
DOM中的空白符
DOM 中的空白符會讓處理節(jié)點結(jié)構(gòu)時增加不少麻煩。在Mozilla 的軟件中铜幽,原始文件里所有空白符都會在 DOM 中出現(xiàn)(不包括標簽內(nèi)含的空白符)滞谢。這樣的處理方式有其必要之處,一方面編輯器中可逕行排列文字除抛、二方面 CSS 里的 white-space: pre
也才能發(fā)揮作用狮杨。 如此一來就表示:
有些空白符會自成一個文本節(jié)點。
有些空白符會與其他文本節(jié)點合成為一個文本節(jié)點到忽。
換句話說禾酱,下面這段 HTML 代碼對應(yīng)的 DOM 節(jié)點結(jié)構(gòu)會如附圖所示,其中\n
代表換行符:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<html>
<head>
<title>My Document</title>
</head>
<body>
<h1>Header</h1>
<p>
Paragraph
</p>
</body> </html>
</pre>
對應(yīng)的DOM樹绘趋,如下圖所示:
這么一來颤陶,要使用 DOM 游走于節(jié)點結(jié)構(gòu)間又不想要無用的空白符時,會有點困難陷遮。
以下的 JavaScript 代碼定義了許多函數(shù)滓走,能夠讓你在處理 DOM 中的空白符時輕松點:
DOM的遍歷
如果你閱讀了上面的的內(nèi)容,或許你已經(jīng)意識到帽馋,DOM看起來就像一個巨大的樹 —— 一棵巨大的樹搅方,它的元素掛載在樹枝上。為了獲得更多的技術(shù)绽族,DOM中的元素被安排在一個層次結(jié)構(gòu)中姨涡,它定義了你最終在瀏覽器中看到的內(nèi)容:
這個層次結(jié)構(gòu)用于幫助我們組織HTML元素。它還用于幫助你的CSS樣式規(guī)則理解什么樣式適用于哪些東西吧慢。從JavaScript角度來看涛漂,這個層次結(jié)構(gòu)確實增加了一點復(fù)雜性。你會花相當多的時間去弄清楚你現(xiàn)在所有的DOM和你需要去的地方。當我們考慮創(chuàng)建新的元素或移動元素時匈仗,這將變得更加明顯瓢剿。這種復(fù)雜性是你需要適應(yīng)的。
找到你的方式
在你找到元素并與它們做一些事情之前悠轩,你首先需要了解元素的位置间狂。我解決這個問題,最簡單的方法就是從頭開始火架,然后一路向下鉴象。這就是我們要做的。
為了更易于幫助在大家理解何鸡,先回到上一節(jié)中的示例中:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<!DOCTYPE html>
<html>
<head>
<meta content="DOM, JavaScript, W3cplus" name="keywords" />
<meta content="DOM系列纺弊,瀏覽器和DOM!" name="description" />
<title>LOL! Sea Otter! Little Kid!</title>
<link href="style.css" rel="stylesheet"/>
</head>
<body>
<div id="container">
<img src="w3cplus_logo.png"/>
<h1>DOM系列學(xué)習(xí)!</h1>
<p class="bodyText">開始學(xué)習(xí)DOM,這是一個有關(guān)于DOM學(xué)習(xí)的系列教程...<p>
<div class="submitButton">next</div>
</div>
<script src="main.js"></script>
</body>
</html>
</pre>
來自DOM頂部的視圖由window
音比、document
和html
元素組成:
由于這三樣?xùn)|西的重要性俭尖,DOM為你提供了通過window
、document
和document.documentElement
訪問它們的方法洞翩。
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
var windowObject = window;
var documentObject = document; var htmlElement = document.documentElement;
</pre>
需要注意的一點是稽犁,window
和document
都是全局屬性。不必要明確的聲明它們骚亿,可以直接從容器里拿出來用就行了已亥。
往往,最頂層的樹節(jié)點可以直接作為document
屬性使用来屠,比如:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<html> = document.documentElement
</pre>
頂部文檔節(jié)點document.documentElement
虑椎,其對應(yīng)的就是<html>
的DOM節(jié)點。另外一個廣泛使用的DOM節(jié)點是<body>
元素俱笛,其對應(yīng)的是document.body
:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<body> = document.body
</pre>
同樣的捆姜,<head>
標簽可以用document.head
。
不過有一點需要注意:
document.body
有可能為null
迎膜。當腳本在訪問不存在的元素時泥技,返回的值將會為null
。
比如磕仅,當你的腳本在</head>
中運行珊豹,比如document.body
是將返回的值將是null
,因為瀏覽器還沒有讀取它榕订。但在</body>
中的<script>
中返回的則是<body>
元素:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
<html>
<head>
<script> console.log('From head:', document.body) // => null</script>
</head>
<body>
<script> console.log('From body:', document.body) // => HTMLBodyElement</script>
</body> </html>
</pre>
上面我們所看到的是html
店茶、head
和body
元素的獲取。但事實上劫恒,一旦你進入HTML元素級別贩幻,你的DOM將開始分支并變得更有趣。在這一點上,你有幾種獲取DOM的方式段直。通過使用querySelector()
和querySelectorAll()
可以幫助你精確地獲取你想要獲取的DOM元素吃溅∪艿或許你已經(jīng)在項目中大量使用這兩種方法了鸯檬。但事實上,對于許多實際案例來說螺垢,這兩種方法太過局限喧务。
有時候,你不知道你想去哪里枉圃。querySelector()
和querySelectorAll()
主法在這里無法幫助您功茴。你只想上車然后開車,并想找到你想要去的地方孽亲】泊回到DOM的世界當中時,你會發(fā)現(xiàn)自己一直處理這個位置返劲。這就是DOM提供的各種內(nèi)置屬性玲昧,所有的Motorcycle Diaries將會幫助你,接下來我們將看看這些屬性篮绿。
能夠幫助你的是知道所有的DOM元素都至少有一個組合孵延,包括父母(Parents)、兄弟姐妹(Siblings)和子元素(Children)亲配。為了更直觀的幫助大家理解尘应,來看下圖,下圖中包含div
的script
的一個樹形圖:
div
和script
是兄弟元素吼虎。他們是兄弟元素的原因是他們共有一個相同的父元素body
犬钢。script
元素沒有子元素,但是div
元素有四個子元素思灰,img
玷犹、h1
、p
和div
官辈。這四個元素也相互被稱為兄弟元素箱舞,同樣的是因為他們有相同的父元素。這其實很好理解拳亿,如果你閱讀了文章前面的DOM樹相關(guān)的內(nèi)容晴股,你會發(fā)現(xiàn)它們就像現(xiàn)實的生活中一樣,父母肺魁、孩子 和兄弟姐妹的關(guān)系基于你所關(guān)注的樹的位置(對應(yīng)的就是家族族譜)电湘。幾乎每個元素,取決于你看它們的角度,可以扮演多個家庭角色寂呛。
為了更好的理解怎诫,DOM中提供了一些對應(yīng)的屬性(這些屬性具有一定的依賴關(guān)系)。包括:firstChild
贷痪、lastChild
幻妓、parentNode
、children
劫拢、previousSibling
和nextSibling
肉津。從他們的名稱上來看,就可以推出這些屬性的作用舱沧。這幾個屬性結(jié)合在一起將構(gòu)建一個DOM遍歷鏈接圖发钝,允許在DOM節(jié)點間找到你想要找到的DOM:
為了更好的理解DOM遍歷相關(guān)的知識點简烤,咱們接下來將圍繞這幾個屬性來展開幽邓。
兄弟姐妹和父母打交道
在這些DOM屬性中娶吞,最容易處理的是父母和兄弟姐妹。對應(yīng)的屬性有parentNode
牵寺、previousSibling
和nextSibling
悍引。下面這張圖將幫助你了解這三個屬性是如何工作的:
這張圖雖然有點零亂,但是你仔細看的話缸剪,你可以理清楚它們之間的關(guān)系吗铐,以及他們之間發(fā)生了什么。parentNode
屬性指向元素的父元素杏节。previousSibling
和nextSibling
屬性允許元素元素它的前一個或下一個兄弟元素唬渗。你可以在圖中看到箭頭的方向指向。最后一行奋渔,img
的nextSibling
是div
镊逝,相應(yīng)的div
的previousSibling
是img
元素。不管是通過img
或div
的parentNode
屬性都將把我們帶入到第二行中的div
(事實上就是img
和div
的元素)嫉鲸。通過上圖撑蒜,大家理解起來是不是很簡單。
子元素打交道
上面咱們看到的是如何通過DOM的屬性來訪問兄弟元素和父元素玄渗,事實上座菠,除此之外,DOM還提供一些屬性可以訪問元素的子元素藤树,比如firstChild
浴滴、lastChild
和children
。同樣用一圖來向大家展示:
firstChild
和lastChild
屬性是指父元素的第一個和最后一個子元素岁钓。如果父類只有一個子元素升略,就像例子中的body
元素一樣微王,firstChild
和lastChild
都指向相同的元素div
。如果一個元素沒有子元素品嚣,那么firstChild
和lastChild
屬性將返回一個null
炕倘。
與其他屬性相比,其中children
屬性相對而方要更為復(fù)雜一些翰撑。當你在父類上訪問children
屬性時罩旋,基本上會得到父元素的子元素集合。這個集合并不是數(shù)組额嘿,但它確實有一些類似數(shù)組的能力瘸恼,就是大家所說的類數(shù)組劣挫,其具有length
屬性册养,可以通過[]
或item()
來索引集合中具體的元素。比如上圖中的div.children[0]
訪問到的是第一個img
元素压固。
在DOM中獲取子節(jié)點球拦,除了前面提到的三個屬性之外,還有一個childNodes
屬性帐我,不過它和children
有一個很明顯的區(qū)別:
children
只獲取子節(jié)點(即子元素)坎炼,而childNodes
除了獲取的子節(jié)點還包括文本節(jié)點。
除此之外拦键,還有一個特殊的函數(shù)hasChildNodes()
可以用來判斷某個元素是否包含子節(jié)點谣光。
這個時候,你把它們放在一起芬为,你就可以對DOM進行遍歷萄金。也可以做一些事情。比如媚朦,檢查某個元素是否有子元素存在氧敢,我們就可以這樣做:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
let bodyElement = document.body
if (bodyElement.firstChild) {
// 這里做你想做的事情... }
</pre>
如果body
沒有子節(jié)點,那么if
語獎將返回null
询张。當然孙乖,你也可以使用bodyElement.lastChild
或bodyElement.children
做為if
語句的條件。
再來看另一個簡單示例份氧,前面提到過了唯袄,通過children
可以獲取某個元素的所有子節(jié)點(前提是這個元素有子元素存在)。這個時候得到的是一個類數(shù)組蜗帜,如查你要獲取到該元素中的每個子節(jié)點恋拷,就需要使用for
循環(huán)來處理:
<pre class="" style="margin: 0px; padding: 0.5em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: 0.544px; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; overflow: auto; font-family: monospace, monospace; font-size: 14px; background-color: rgb(0, 43, 54); color: rgb(131, 148, 150);">
var bodyElement = document.body;
for (var i = 0; i < bodyElement.children.length; i++) {
var childElement = bodyElement.children[i];
document.writeln(childElement.tagName);
}
</pre>
通過元素遍歷DOM
上面咱們看到的是通過DOM節(jié)點來遍歷DOM。比如childNodes
屬性钮糖,除了可以獲取元素節(jié)點之外梅掠,還可以獲取文本節(jié)點酌住,甚至是注釋節(jié)點。但很多時候阎抒,對于DOM的操作酪我,咱們只需要獲取想要的DOM元素節(jié)點,而不需要考慮文本和注釋節(jié)點且叁。這個時候咱們只需要操作元素節(jié)點即可都哭,這對應(yīng)DOM中操作元素節(jié)點的一些屬性。同樣的使用下圖來向大家闡述逞带,易于理解:
和前面相比欺矫,這里的屬性多了Element
這個詞,其對應(yīng)的含義:
children
:元素節(jié)點的子元素firstElementChild
展氓、lastElementChild
:元素的第一個或最后一個子元素previousElementSibling
和nextElementSibling
:元素的前一個或后一個相鄰元素parentElement
:元素的父元素
總結(jié)
這篇文章是DOM系列的第二篇文章穆趴,主要介紹了DOM樹和DOM的遍歷。前一部分只要介紹了DOM樹遇汞,簡單的理解未妹,任何一個HTML文檔都可以類似于家族的族普來繪制對應(yīng)的DOM樹。通過DOM樹可以理清楚每個DOM元素(或者說DOM節(jié)點)之間的關(guān)系空入。比如络它,父子關(guān)系、兄弟關(guān)系等歪赢。
另外化戳,在DOM中找到對應(yīng)的元素是每位JavaScript開發(fā)人員都應(yīng)該需要掌握的技巧之一。這篇文章的后一部分主要向大家介紹了如何對DOM進行遍歷埋凯,其實就是通過DOM的屬性怎么獲取DOM的元素或節(jié)點点楼。簡單的歸納一下,分為:
向上獲取递鹉,比如
parentNode
盟步、parentElement
和closest
;向下獲取躏结,比如
querySelector()
却盘、querySelectorAll()
、children
媳拴、firstChildren
黄橘、lastChildren
和childNodes
兄弟元素(節(jié)點),比如
nextElementSibling
屈溉、previousElementSibling
塞关、nextSibling
和previousSibling
如果文中有不對之處,或者你有更好的經(jīng)驗子巾,歡迎在下面的評論中與我們一起分享帆赢。最后要說明的是小压,文章中有些圖片來自互聯(lián)網(wǎng),如涉及侵權(quán)椰于,煩請告之怠益。