譯者:前端小智
來源:valentinog
點贊再看,養成習慣
本文 GitHub:github.com/qq449245884… 上已經收錄,更多往期高贊文章的分類,也整理了很多我的文件,和教程資料。歡迎Star和完善,大家面試可以參照考點複習,希望我們一起有點東西。
個人專欄 ES6 深入淺出已上線,深入ES6 ,通過案例學習掌握 ES6 中新特性一些使用技巧及原理,持續更新中,←點選可訂閱。
文字主要介紹 **文件物件模型(DOM)**瞭解什麼是DOM操作,以及如何使用砶 DOM API 與 JS 中的 Web 頁面進行互動。
什麼是 DOM ?
DOM(文件物件模型)是針對於xml但是擴充套件用於HTML的應用程式程式設計介面,定義了訪問和操作HTML的文件的標準。
W3C文件物件模型是中立於平臺和語言之間的介面,它允許程式和指令碼動態的訪問和更新文件的內容、結構、樣式。總之HTML是關於如何獲取、修改、新增和刪除HTML元素的標準。
DOM 分層節點
DOM的分層節點一般被稱作是DOM樹,樹中的所有節點都可以通過指令碼語言例如JS進行訪問,所有HTMlL元素節點都可以被建立、新增或者刪除。
在DOM分層節點中,頁面就是用分層節點圖表示的。
- 整個文件是一個文件節點,就想是樹的根一樣。
- 每個HTML元素都是元素節點。
- HTML元素內的文字就是文字節點。
- 每個HTML屬性時屬性節點。
當我們們訪問一個web頁面時,瀏覽器會解析每個HTML元素,建立了HTML文件的虛擬結構,並將其儲存在記憶體中。接著,HTML頁面被轉換成樹狀結構,每個HTML元素成為一個葉子節點,連線到父分支。 考慮以下 Html 結構:
<!DOCTYPE html>
<html lang="en">
<head>
<title>A super simple title!</title>
</head>
<body>
<h1>A super simple web page!</h1>
</body>
</html>
複製程式碼
在這個結構的頂部有一個document
,也稱為根元素,它包含另一個元素:html
。 html
元素包含一個head
,而 head
又有一個title
。 然後body
包含一個h1
。 每個HTML元素都由特定型別(也稱為介面)表示,並且可能包含文字或其他巢狀元素:
document (HTMLDocument)
|
| --> html (HTMLHtmlElement)
|
| --> head (HtmlHeadElement)
| |
| | --> title (HtmlTitleElement)
| | --> text: "A super simple title!"
|
| --> body (HtmlBodyElement)
| |
| | --> h1 (HTMLHeadingElement)
| | --> text: "A super simple web page!"
複製程式碼
每個HTML
元素都來自Element
,但其中很大一部分都是專用的。 我們們可以檢查原型以查詢元素所屬的“種類”。 例如,h1
元素是HTMLHeadingElement
:
document.querySelector('h1').__proto__
// Output: HTMLHeadingElement
複製程式碼
而HTMLHeadingElement
則是HTMLElement
的後代:
document.querySelector('h1').__proto__.__proto__
// Output: HTMLElement
複製程式碼
此時(特別是初學者)可能會對document和window之間的區別產生一些混淆。接下來看看它們有何不同!
document 和 window 之間的區別
簡單來說,document
是window
的一個物件屬性。window
物件表示瀏覽器中開啟的視窗。如果文件包含框架(frame
或 iframe
標籤),瀏覽器會為 HTML 文件建立一個 window
物件,併為每個框架建立一個額外的 window
物件。所有的全域性函式和物件都屬於 window
物件的屬性和方法。
區別:
-
window
指窗體。document
指頁面。document
是window
的一個子物件。 -
使用者不能改變
document.location
(因為這是當前顯示文件的位置)。但是,可以改變window.location
(用其它文件取代當前文件)window.location
本身也是一個物件,而document.location
不是物件。
document介面有許多實用方法,比如querySelector()
,它是用於查詢給定頁面內HTML元素的方法:
document.querySelector('h1');
複製程式碼
window
表示當前的瀏覽器,下面程式碼與上面等價:
window.document.querySelector('h1');
複製程式碼
當然,更常見的是用第一種方式。
window是一個全域性物件,可以從瀏覽器中執行的任何JS程式碼直接訪問。 window
暴露了很多屬性和方法,如:
window.alert('Hello world'); // Shows an alert
window.setTimeout(callback, 3000); // Delay execution
window.fetch(someUrl); // make XHR requests
window.open(); // Opens a new tab
window.location; // Browser location
window.history; // Browser history
window.navigator; // The actual user agent
window.document; // The current page
複製程式碼
因為這些屬性和方法也是全域性的,所以也可以這樣訪問它們
alert('Hello world'); // Shows an alert
setTimeout(callback, 3000); // Delay execution
fetch(someUrl); // make XHR requests
open(); // Opens a new tab
location; // Browser location
history; // Browser history
navigator; // The actual user agent
document;// The current page
複製程式碼
其中有些我們們都已經很熟悉了,如setTimeout()
的方法。 例如,當我們們想要得知當前使用者的瀏覽器語言時,window.navigator
就非常有用:
if (window.navigator) {
var lang = window.navigator.language;
if (lang === "en-US") {
// show something
}
if (lang === "it-IT") {
// show something else
}
}
複製程式碼
DOM 常用方法
獲取節點
// 通過id號來獲取元素,返回一個元素物件
document.getElementById(idName)
// 通過name屬性獲取id號,返回元素物件陣列
document.getElementsByName(name)
// 通過class來獲取元素,返回元素物件陣列
document.getElementsByClassName(className)
// 通過標籤名獲取元素,返回元素物件陣列
document.getElementsByTagName(tagName)
複製程式碼
獲取/設定元素的屬性值:
// 括號傳入屬性名,返回對應屬性的屬性值
element.getAttribute(attributeName)
// 傳入屬性名及設定的值
element.setAttribute(attributeName,attributeValue)
複製程式碼
建立節點Node
// 建立一個html元素,這裡以建立h3元素為例
document.createElement("h3")
// 建立一個文字節點;
document.createTextNode(String);
// 建立一個屬性節點,這裡以建立class屬性為例
document.createAttribute("class");
複製程式碼
增添節點
// 往element內部最後面新增一個節點,引數是節點型別
element.appendChild(Node);
// 在element內部的中在existingNode前面插入newNode
elelment.insertBefore(newNode,existingNode);
複製程式碼
刪除節點
//刪除當前節點下指定的子節點,刪除成功返回該被刪除的節點,否則返回null
element.removeChild(Node)
複製程式碼
DOM常用屬性
獲取當前元素的父節點
// 返回當前元素的父節點物件
element.parentNode
複製程式碼
獲取當前元素的子節點
// 返回當前元素所有子元素節點物件,只返回HTML節點
element.chlidren
// 返回當前元素多有子節點,包括文字,HTML,屬性節點。(回車也會當做一個節點)
element.chilidNodes
// 返回當前元素的第一個子節點物件
element.firstChild
// 返回當前元素的最後一個子節點物件
element.lastChild
複製程式碼
獲取當前元素的同級元素
// 返回當前元素的下一個同級元素 沒有就返回null
element.nextSibling
// 返回當前元素上一個同級元素 沒有就返回 null
element.previousSibling
複製程式碼
獲取當前元素的文字
// 返回元素的所有文字,包括html程式碼
element.innerHTML
// 返回當前元素的自身及子代所有文字值,只是文字內容,不包括html程式碼
element.innerText
複製程式碼
獲取當前節點的節點型別
// 返回節點的型別,數字形式(1-12)
// 常見幾個1:元素節點,2:屬性節點,3:文字節點。
node.nodeType
複製程式碼
設定樣式
// 設定元素的樣式時使用style
element.style.color=“#eea”;
複製程式碼
DOM 操作
DOM中的每個HTML元素也是一個節點,可以像這樣查詢節點:
document.querySelector('h1').nodeType;
複製程式碼
上面會返回1
,它是Element
型別的節點的識別符號,還可以檢查節點名稱:
document.querySelector('h1').nodeName;
"H1"
複製程式碼
上面的示例返回大寫的節點名。但是需要理解的最重要的概念是,我們們主要使用DOM中的兩種型別的節點:
- 元素節點
- 文字節點
建立元素節點,可以通過 createElement
方法:
var heading = document.createElement('h1');
複製程式碼
建立文字節點,可能通過 createTextNode
方法:
var text = document.createTextNode('Hello world');
複製程式碼
接著將兩個節點組合在一起,然後新增到 body
上:
var heading = document.createElement('h1');
var text = document.createTextNoe('Hello world');
heading.appendChild(text);
document.body.appendChild(heading)
複製程式碼
在學習Dom操作時候,這些方法需要牢記並熟練使用的。
目前像我們們用這種方式建立和操作元素,是屬於命令式DOM操作。現代前端庫通過支援宣告性方法來解決這個問題,如 JQuery,我們們可以宣告需要什麼HTML元素,其它就由庫來完成。
DOM 操作和 jQuery
大部分可能會想,我們們直接使用 JQ 不就行了,為啥還要用如createElement
這些原生的方法,多費勁。
請注意jQuery正在漸漸消失。Bootstrap 5將把它從依賴項中刪除,還有很多專案也在刪除它。這背後有一個合理的原因:原生DOM API提供了大量像JQ這樣操作DOM的簡便方法,足以替代jQuery一些常用的DOM操作。
如果只是想進行簡單的互動和操作,請使用普通的JS。我們們甚至可以建立自己的迷你框架來抽象最常見的操作:建立元素、追加、建立文字。
總結
DOM是瀏覽器建立並保留在記憶體中的網頁的虛擬副本。建立、修改、刪除 HTML 元素,這些屬於 “DOM 操作”。在過去即使對於更簡單的任務,我們們也要依賴於 jQuery,但今天原生 API 已經互相相容並且足夠成熟足以替代 jQuery 了。
jQuery不會很快消失,但是每個JS開發人員都必須知道如何使用原生API操作DOM。這樣做有很多原因,額外的庫增加了JS應用程式的載入時間和大小,更不用說DOM操作在技術面試也經常出現。
操作 DOM 最常用的方法是 document.createElement()
用於建立新的 HTML 元素,document.createTextNode()
用於在 DOM 內建立文字節點。需要注意的是 .appendChild()
用於將新的 HTML 元素或文字節點附加到現有元素。
雖然很好的瞭解本機 API 是很好的,但是現代前端庫也提供了無可置疑的好處。儘管用“原生” JS 去構建大型JS 程式確實是可行的,但有時 Angular、React、Vue可以提供很多幫助。僅使用 JavaScript 來處理更簡單的原型和中小型應用也是明智之舉。
原文:www.valentinog.com/blog/html-t…
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
交流
乾貨系列文章彙總如下,覺得不錯點個Star,歡迎 加群 互相學習。
因為篇幅的限制,今天的分享只到這裡。如果大家想了解更多的內容的話,可以去掃一掃每篇文章最下面的二維碼,然後關注我們們的微信公眾號,瞭解更多的資訊和有價值的內容。