核心要點
NodeList.js 作為 jQuery 的 DOM 操作替代方案,提供類似的功能,但體積更小(壓縮後 4k),並利用了原生瀏覽器 API 的改進。
與 jQuery 不同,NodeList.js 將節點數組視為單個節點,從而實現更簡潔的代碼和更輕鬆的 NodeList 對像操作。
NodeList.js 包含用於設置和獲取屬性、調用特定於元素的方法以及訪問 NodeList 中節點的特殊方法,以及等同於 jQuery 的 prevObject
屬性的 owner
屬性。
NodeList.js 與特定版本以後的主流瀏覽器兼容(Firefox 6 、Safari 5.0.5 、Chrome 6 、IE 9 、Opera 11.6 ),並自動更新以包含瀏覽器新增的方法/屬性。
p.tip { background-color: rgba(128,128,128,0.05); border-top-right-radius: 5px; border-bottom-right-radius: 5px; padding: 15px 20px; border-left: 10px solid rgba(128,128,128,0.075); }
近年來,jQuery 已成為 Web 上事實上的 JavaScript 庫。它消除了許多跨瀏覽器的不一致性,並為客戶端腳本添加了一層受歡迎的語法糖。它抽象化處理的主要痛點之一是 DOM 操作,但自 jQuery 問世以來,原生瀏覽器 API 已得到顯著改進,“你可能不需要 jQuery” 的理念開始流行起來。
原因如下:
addEventListener
代替 attachEvent
。 問題在於,與 jQuery 相比,使用原生(或純)JavaScript 進行 DOM 操作可能很麻煩。這是因為您必須編寫更多冗餘代碼,並處理瀏覽器無用的 NodeList。
首先,讓我們看看 MDN 對 NodeList 的定義:
NodeList 對像是節點的集合,例如 Node.childNodes
和 document.querySelectorAll
方法返回的那些節點。
有時還存在動態 NodeList(這可能會令人困惑):
在某些情況下,NodeList 是動態集合,這意味著 DOM 中的更改會反映在集合中。例如,Node.childNodes
是動態的。
這可能是一個問題,因為您無法分辨哪些是動態的,哪些是靜態的。除非您從 NodeList 中移除每個節點,然後檢查 NodeList 是否為空。如果為空,則表示您擁有一個動態 NodeList(這只是一個壞主意)。
此外,瀏覽器沒有提供任何有用的方法來操作這些 NodeList 對象。
例如,不幸的是,無法使用 forEach
循環遍歷節點:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); nodes.forEach(function(node) { // do something }); // 错误:nodes.forEach 不是函数</code>
因此,您必須執行以下操作:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }</code>
或者甚至只能使用“hack”:
<code class="language-javascript">[].forEach.call(document.querySelectorAll('div'), function(node) { // do something });</code>
瀏覽器的原生 NodeList 只有一個方法:item
。它通過索引從 NodeList 返回一個節點。當我們可以像使用數組一樣訪問該節點(使用 array[index]
)時,它完全沒用:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); nodes.item(0) === nodes[0]; // true</code>
這就是 NodeList.js 的用武之地——使使用瀏覽器原生 API 操作 DOM 變得像使用 jQuery 一樣容易,但僅需 4k 壓縮大小。
我創建 NodeList.js 是因為我一直使用原生 DOM API,但希望使它們更簡潔,從而減少編寫代碼時的許多冗餘(例如 for 循環)。
NodeList.js 是原生 DOM API 的一個包裝器,它允許您操作節點數組(即我的 NodeList),就好像它是一個單個節點一樣。這為您提供了比瀏覽器原生 NodeList 對象更多的功能。
如果您覺得這不錯,請從官方 GitHub 存儲庫獲取 NodeList.js 的副本,並繼續閱讀本教程的其餘部分。
選擇 DOM 節點很簡單:
$$(selector);
// 返回我的 NodeList
此方法在後台使用 querySelectorAll(selector)
。
很高興您提出這個問題。讓我們將原生 JS、jQuery 和 NodeList.js 進行比較。
假設我們有三個按鈕:
讓我們將每個按鈕的文本更改為“點擊我”:
<code class="language-javascript">var buttons = document.querySelectorAll('button'); // 返回浏览器无用的 NodeList for(var i = 0, l = buttons.length; i < l; i++) { buttons[i].textContent = 'Click Me'; }</code>
<code class="language-javascript">$('button').text('Click Me');</code>
<code class="language-javascript">$$('button').textContent = 'Click Me';</code>
在這裡,我們看到 NodeList.js 可以有效地將 NodeList 視為單個節點。也就是說,我們引用了一個 NodeList,並將它的 textContent
屬性設置為“點擊我”。然後,NodeList.js 將對 NodeList 中的每個節點執行此操作。很巧妙,對吧?
如果我們想要方法鏈(類似於 jQuery),我們會執行以下操作,這將返回對 NodeList 的引用:
<code class="language-javascript">$$('button').set('textContent', 'Click Me');</code>
現在,讓我們向每個按鈕添加一個點擊事件監聽器:
<code class="language-javascript">var buttons = document.querySelectorAll('button'); // 返回浏览器无用的 NodeList for(var i = 0, l = buttons.length; i < l; i++) { buttons[i].addEventListener('click', function() { this.classList.add('clicked'); }); }</code>
<code class="language-javascript">$('button').on('click', function() { $(this).addClass('click'); // 或将 jQuery 与原生混合使用 `classList`: this.classList.add('clicked'); });</code>
<code class="language-javascript">$$('button').addEventListener('click', function() { this.classList.add('clicked'); });</code>
好的,所以 jQuery 的 on
方法相當不錯。我的庫使用瀏覽器的原生 DOM API(因此是 addEventListener
),但這並不會阻止我們為該方法創建別名:
<code class="language-javascript">$$.NL.on = $$.NL.addEventListener; $$('button').on('click', function() { this.classList.add('clicked'); });</code>
不錯!這演示了我們添加自己方法的方式:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); nodes.forEach(function(node) { // do something }); // 错误:nodes.forEach 不是函数</code>
NodeList.js 確實繼承自 Array.prototype
,但不是直接繼承,因為某些方法已更改,因此使用它們與 NodeList(節點數組)一起使用是有意義的。
push
和 unshift
例如:push
和 unshift
方法只能將節點作為參數,否則會拋出錯誤:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }</code>
因此,push
和unshift
都返回NodeList 以允許方法鏈,這意味著它與JavaScript 的原生Array#push
或Array#unshift
方法不同,後者接受任何內容並返回數組的新長度。如果我們確實想要 NodeList 的長度,我們只需使用 length
屬性。
這兩個方法,就像 JavaScript 的原生數組方法一樣,都會更改 NodeList。
concat
concat
方法將接受以下內容作為參數:
<code class="language-javascript">[].forEach.call(document.querySelectorAll('div'), function(node) { // do something });</code>
concat
是一個遞歸方法,因此這些數組可以像我們希望的那樣深,並且會被展平。但是,如果傳遞的數組中的任何元素不是節點、NodeList 或 HTMLCollection,它將拋出錯誤。
concat
返回一個新的 NodeList,就像 javascript 的 Array#concat
方法一樣。
pop
、shift
、map
、slice
、filter
pop
和 shift
方法都可以採用可選參數,說明要從 NodeList 中彈出或移位多少個節點。與 JavaScript 的原生 Array#pop
或 Array#shift
不同,後者總是彈出或移位數組中的一個元素,而不管傳遞什麼作為參數。
如果每個映射值都是一個節點,map
方法將返回一個 NodeList;如果不是,則返回映射值的數組。
slice
和 filter
方法的作用與在真實數組中的作用一樣,但會返回一個 NodeList。
由於 NodeList.js 沒有直接繼承自 Array.prototype
,因此如果在加載 NodeList.js 後向 Array.prototype
添加方法,則不會繼承該方法。
您可以在此處查看 NodeList.js 的其餘數組方法。
NodeList.js 有四個獨特的方法,以及一個名為 owner
的屬性,它等同於 jQuery 的 prevObject
屬性。
get
和 set
方法:某些元素具有特定於該類型元素的屬性(例如,錨標記上的 href
屬性)。這就是為什麼 $$('a').href
將返回未定義的原因——因為它不是 NodeList 中每個元素都繼承的屬性。這就是我們如何使用 get
方法訪問這些屬性的方法:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); nodes.forEach(function(node) { // do something }); // 错误:nodes.forEach 不是函数</code>
set
方法可用於為每個元素設置這些屬性:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }</code>
set
還返回 NodeList 以允許方法鏈。我們可以在 textContent
等方面使用它(兩者都等效):
<code class="language-javascript">[].forEach.call(document.querySelectorAll('div'), function(node) { // do something });</code>
我們還可以在一次調用中設置多個屬性:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); nodes.item(0) === nodes[0]; // true</code>
以上所有操作都可以使用任意屬性完成,例如 style
:
<code class="language-javascript">var buttons = document.querySelectorAll('button'); // 返回浏览器无用的 NodeList for(var i = 0, l = buttons.length; i < l; i++) { buttons[i].textContent = 'Click Me'; }</code>
call
方法call
方法允許您調用特定於元素的方法(例如,視頻元素上的 pause
):
<code class="language-javascript">$('button').text('Click Me');</code>
item
方法item
方法等同於 jQuery 的 eq
方法。它返回一個 NodeList,其中只包含傳遞索引的節點:
<code class="language-javascript">$$('button').textContent = 'Click Me';</code>
owner
屬性owner
屬性等同於 jQuery 的 prevObject
。
<code class="language-javascript">$$('button').set('textContent', 'Click Me');</code>
btns.style
返回樣式數組,而 owner
將返回 style
所映射的 NodeList。
我的庫與所有主要的新瀏覽器兼容,如下所述。
瀏覽器
版本
現在我們終於可以使用有用的 NodeList 對象了!
對於大約 4k 的壓縮大小,您可以獲得上述所有功能以及更多功能,您可以在 NodeList.js 的 GitHub 存儲庫中了解所有這些功能。
由於 NodeList.js 使用瀏覽器作為依賴項,因此無需進行任何升級。每當瀏覽器向 DOM 元素添加新方法/屬性時,您都可以通過 NodeList.js 自動使用這些方法/屬性。所有這一切都意味著您唯一需要擔心的棄用是瀏覽器刪除的方法。這些通常是使用率非常低的方法,因為我們不能破壞 Web。
那麼您怎麼看?您會考慮使用這個庫嗎?是否缺少任何重要功能?我很樂意在下面的評論中聽到您的意見。
NodeList 和 HTMLCollection 都是節點集合。它們之間的主要區別在於 NodeList 可以包含任何節點類型,而 HTMLCollection 是元素節點的集合。 HTMLCollection 也是動態的,這意味著當文檔結構發生更改時,它會自動更新。另一方面,NodeList 是靜態的,不會更新以反映文檔中的更改。
您可以使用 Array.from()
方法或展開運算符將 NodeList 轉換為數組。以下是如何操作:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); nodes.forEach(function(node) { // do something }); // 错误:nodes.forEach 不是函数</code>
jQuery 的鍊式機制通過在進行更改之前存儲之前的對象來工作。這允許您使用 .end()
方法恢復到之前的狀態。如果您想獲取實際的 DOM 元素,可以使用 .get()
方法或數組表示法。
您可以使用 for 循環、for...of 循環或 forEach()
方法循環遍歷 NodeList。這是一個使用 for 循環的示例:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); for(var i = 0, l = nodes.length; i < l; i++) { // do something with nodes[i] }</code>
jQuery 中的 .prev()
方法用於選擇所選元素的緊鄰前一個同級元素。如果提供了選擇器,則只有在匹配該選擇器時才會檢索前一個同級元素。
雖然 jQuery 在發佈時是一個改變遊戲規則的東西,但現代 JavaScript 生態系統已經發生了顯著變化。許多使 jQuery 受歡迎的功能現在都內置於 JavaScript 本身。但是,jQuery 仍然被廣泛使用和維護,它可能是某些項目的良好選擇。
您可以使用數組表示法或 item()
方法從 NodeList 中選擇特定節點。以下是如何操作:
<code class="language-javascript">[].forEach.call(document.querySelectorAll('div'), function(node) { // do something });</code>
NodeList 不是數組,因此它沒有像 map、filter 和 reduce 這樣的方法。但是,您可以將 NodeList 轉換為數組,然後使用這些方法。
querySelector
返回文檔中與指定的 CSS 選擇器匹配的第一個元素,而 querySelectorAll
返回與 CSS 選擇器匹配的所有元素的 NodeList。
您可以通過檢查其 length
屬性來檢查 NodeList 是否為空。如果長度為 0,則 NodeList 為空。以下是如何操作:
<code class="language-javascript">var nodes = document.querySelectorAll('div'); nodes.item(0) === nodes[0]; // true</code>
以上是失去jQuery膨脹的詳細內容。更多資訊請關注PHP中文網其他相關文章!