回到基礎:什麼是DOM及DOM操做?

譯者:前端小智
來源:valentinog

我的專欄 ES6 深刻淺出已上線,深刻ES6 ,經過案例學習掌握 ES6 中新特性一些使用技巧及原理,持續更新中,←點擊可訂閱。html

點贊再看,養成習慣

本文 GitHub https://github.com/qq44924588... 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。前端

文本主要介紹文檔對象模型(DOM),瞭解什麼是DOM操做,以及如何使用砶 DOM API 與 JS 中的 Web 頁面進行交互。node

什麼是 DOM ?

DOM(文檔對象模型)是針對於xml可是擴展用於HTML的應用程序編程接口,定義了訪問和操做HTML的文檔的標準。git

W3C文檔對象模型是中立於平臺和語言之間的接口,它容許程序和腳本動態的訪問和更新文檔的內容、結構、樣式。總之HTML是關於如何獲取、修改、添加和刪除HTML元素的標準。github

DOM 分層節點

DOM的分層節點通常被稱做是DOM樹,樹中的全部節點均可以經過腳本語言例如JS進行訪問,全部HTMlL元素節點均可以被建立、添加或者刪除。web

在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,也稱爲根元素,它包含另外一個元素:htmlhtml元素包含一個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

此時(特別是初學者)可能會對documentwindow之間的區別產生一些混淆。接下來看看它們有何不一樣!

document 和 window 之間的區別

簡單來講,documentwindow的一個對象屬性。window 對象表示瀏覽器中打開的窗口。若是文檔包含框架(frameiframe 標籤),瀏覽器會爲 HTML 文檔建立一個 window 對象,併爲每一個框架建立一個額外的 window 對象。全部的全局函數和對象都屬於 window 對象的屬性和方法。

區別:

  1. window 指窗體。document指頁面。documentwindow的一個子對象。
  2. 用戶不能改變 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 來處理更簡單的原型和中小型應用也是明智之舉。

原文:https://www.valentinog.com/bl...

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

交流

乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。

https://github.com/qq44924588...

我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!

關注公衆號,後臺回覆福利,便可看到福利,你懂的。

clipboard.png

相關文章
相關標籤/搜索