NodeList.js
使得在Nodes
Array
上使用本機 DOM API就像jQuery
一樣簡單,其優點是它非常小,大約4k 縮小,並且瀏覽器作為依賴項(這是最有趣的部分) 。
您會注意到的第一件事是我使用$$
,我選擇它來選擇DOM Nodes
的原因是因為如果您打開開發工具並輸入以下內容:
$$ ( 'div' ) ; // Will return a NodeList
NodeList.js
用法: HTML
: < body >
< div id =" container " class =" cont " >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
< div class =" child " > </ div >
</ div >
</ body >
#container
的子級開始:以下每個都傳回一個Array of Nodes
(又稱我的NodeList
,而不是瀏覽器的本機NodeList
)
// Method 1
$$ ( '#container div' ) ;
// Method 2
$$ ( '#container' ) . children ;
// Method 3
$$ ( 'div div' ) ;
如果您傳遞查詢字串,則可以將第二個參數作為範圍傳遞:
let container = document . getElementById ( 'container' ) ;
$$ ( 'div' , container ) ;
這相當於:
// Just this doesn't return my NodeList, but the browser's NodeList
container . querySelectorAll ( 'div' ) ;
您可以將節點作為參數傳遞:
$$(document, document.body); // returns NodeList
您也可以傳遞 1 個節點Array
或NodeList
或HTMLCollection
不會被展平,要展平使用concat()
:
$$([document, document.body]); // returns NodeList
Node
的屬性:您通常會如何做:
let children = document . getElementsByClassName ( 'child' ) ;
現在您將獲得#container
子級的屬性:
for ( let i = 0 , l = children . length ; i < l ; i ++ ) {
children [ i ] . id ; // ''
children [ i ] . nodeName ; // 'DIV'
children [ i ] . className ; // 'child'
}
以下是使用nodeList.js
的方法:
$$ ( '.child' ) . id ; // ['', '' ... x10]
$$ ( '.child' ) . nodeName ; // ['DIV', 'DIV' ... x10]
$$ ( '.child' ) . className ; // ['child', 'child' ... x10]
因此,您將像使用單一Node
一樣讀取每個屬性:)
請注意它如何傳回屬性值的Array
,這意味著您可以透過index
選擇它們並對它們使用任何Array Methods
,您將在到達循環部分時看到。
node
上設定屬性:讓我們繼續使用children
變量,這就是設定children
屬性的方法:
for ( let i = 0 , l = children . length ; i < l ; i ++ ) {
children [ i ] . className = 'containerChild' ;
children [ i ] . textContent = 'This is some text' ;
}
以下是使用NodeList.js
的方法:
$$ ( '.child' ) . className = 'containerChild' ;
$$ ( '.child' ) . textContent = 'This is some text' ;
node
上呼叫方法:仍然使用children
變數:
讓我們為每個節點新增一個事件偵聽器,儘管event delegation
是最好的,但是為了這個範例:
for ( let i = 0 , l = children . length ; i < l ; i ++ ) {
children [ i ] . addEventListener ( 'click' , function ( ) {
console . log ( this , 'was clicked' ) ;
} ) ;
}
以下是使用NodeList.js
的方法:
$$ ( '.child' ) . addEventListener ( 'click' , function ( ) {
console . log ( this , 'was clicked' ) ;
} ) ;
很酷吧?您可以使用任何Native DOM method
:
讓我們設定一些屬性:
$$ ( '.child' ) . setAttribute ( 'class' , 'child div' ) ;
// For setting the class you could just do:
$$ ( '.child' ) . className = 'child div' ;
點選元素:
$$ ( '.child' ) . click ( ) ;
刪除元素:
$$ ( '.child' ) . remove ( ) ;
我想您已經明白了:每個Node/Element
繼承的任何Native DOM Method
都可以在NodeList
上調用,並且它將在每個元素上調用。
順便說一句:在單一Node
上呼叫時通常會傳回undefined
的所有DOM
方法將傳回相同的NodeList
以允許方法連結。就像setAttribute()
一樣。
使用 for 迴圈和ES6
for-of
:
作為範例,我們將僅從DOM
中刪除節點:
let nodes = $$ ( '.child' ) ;
for ( let i = 0 , l = nodes . length ; i < l ; i ++ ) {
nodes [ i ] . remove ( ) ;
}
for ( let node of nodes ) {
node . remove ( ) ;
}
使用forEach
:
// Removes all Nodes and returns same the NodeList to allow method chaining
$$ ( '.child' ) . forEach ( function ( node ) {
node . remove ( ) ;
} ) ;
// But Just do:
$$ ( '.child' ) . remove ( ) ;
循環遍歷屬性:
// Returns Array of style objects (CSSStyleDeclaration)
let styles = $$ ( '.child' ) . style ;
for ( let i = 0 , l = styles . length ; i < l ; i ++ ) {
styles [ i ] . color = 'red' ;
}
for ( let style of styles ) {
style . color = 'red' ;
}
styles . forEach ( function ( style ) {
style . color = 'red' ;
} ) ;
// OR loop through the nodes themselves
let nodes = $$ ( '.child' ) ;
for ( let i = 0 , l = nodes . length ; i < l ; i ++ ) {
nodes [ i ] . style . color = 'red' ;
}
for ( let node of nodes ) {
node . style . color = 'red' ;
}
nodes . forEach ( function ( node ) {
node . style . color = 'red' ;
} ) ;
// Returns NodeList containing first Node
$$ ( '.child' ) . slice ( 0 , 1 ) ;
映射很容易,只需像在單一節點上一樣取得屬性即可
// Returns an Array of the id of each Node in the NodeList
$$ ( '#container' ) . id ;
// No need for
$$ ( '#container' ) . map ( function ( element ) {
return element . id ;
} ) ;
// Map() Checks if Array is fully populated with nodes so returns a NodeList populated with firstChld nodes
$$ ( '#container div' ) . map ( function ( div ) {
return div . firstChild ;
} ) ;
// Maps the firstChild node and removes it, and returns the NodeList of firstChild Nodes
$$ ( '#container' ) . map ( function ( div ) {
return div . firstChild ;
} ) . remove ( ) ;
// Or:
$$ ( '#container' ) . firstChild . remove ( ) ;
// Filter out the #container div
$$ ( 'div' ) . filter ( function ( div ) {
return ! div . matches ( '#container' ) ;
} ) ;
我想不出在 NodeList 上使用 Reduce 的更好範例(但這是可能的)
let unique = $$ ( 'div' ) . reduce ( function ( set , div ) {
set . add ( div . parentElement ) ;
return set ;
} , new Set ( ) ) ;
還有reduceRight()
下列concat()
方法都會傳回一個新的串聯NodeList
(不影響呼叫concat()
的NodeList
)
let divs = $$ ( 'div' ) ;
// Method 1 passing a Node
let divsAndBody = divs . concat ( document . body ) ;
// Method 2 passing an Array of Nodes
let divsAndBody = divs . concat ( [ document . body ] ) ;
// Method 3 passing a NodeList
let divsAndBody = divs . concat ( $$ ( 'body' ) ) ;
// Method 4 passing an Array of NodeList
let divsAndBody = divs . concat ( [ $$ ( 'body' ) ] ) ;
// Method 5 passing multiple Nodes as arguments
let divsAndBodyAndHTML = divs . concat ( document . body , document . documentHTML ) ;
// Method 6 passing multiple Arrays of Nodes as arguments
let divsAndBodyAndHTML = divs . concat ( [ document . body ] , [ document . documentHTML ] ) ;
// Method 7 passing multiple Arrays of NodeList as are arguments
let divsAndBodyAndHTML = divs . concat ( [ $$ ( 'body' ) ] , [ $$ ( 'html' ) ] ) ;
Concat()
是遞歸的,因此您可以傳遞任意深度的Array
。
現在,如果您傳遞的任何內容不是Node
、 NodeList
、 HTMLCollections
、 Array
或深層Array of Arrays
,且包含Node
、 NodeList
、 HTMLCollections
、 Array
以外的內容,則會拋出Error
。
let divs = $$ ( 'div' ) ;
// Pushes the document.body element, and returns the same NodeList to allow method chaining.
divs . push ( document . body ) ;
let divs = $$ ( 'div' ) ;
// Removes last Node in the NodeList and returns a NodeList of the removed Nodes
divs . pop ( ) ;
pop()
接受一個可選參數,表示要POP 的Nodes
數量
// Removes last 2 Nodes in the NodeList and returns a NodeList of the removed Nodes
divs . pop ( 2 ) ;
let divs = $$ ( 'div' ) ;
// Removes first Node in the NodeList and returns a NodeList of the removed Nodes
divs . shift ( ) ;
shift()
也帶有一個可選參數,表示要SHIFT 的節Nodes
// Removes first 2 Nodes in the NodeList and returns a NodeList of the removed Nodes
divs . shift ( 2 ) ;
let divs = $$ ( 'div' ) ;
// Inserts/unshifts the document.body into the beginning of the NodeList and returns the same NodeList to allow method chaining.
divs . unshift ( document . body ) ;
讓我們用 document.body 取代第一個元素 #container
let divs = $$ ( 'div' ) ;
// Removes the first Element, inserts document.body in its place and returns a NodeList of the spliced Nodes
divs . splice ( 0 , 1 , document . body ) ;
let divs = $$ ( '.child' ) ;
// Gives each div a data-index attribute
divs . forEach ( function ( div , index ) {
div . dataset . index = index ;
} ) ;
// Reverse the NodeList and returns the same NodeList
divs . sort ( function ( div1 , div2 ) {
return div2 . dataset . index - div1 . dataset . index ;
} ) ;
// Returns the same NodeList, but reversed
$$ ( 'div' ) . reverse ( ) ;
我沒有為NodeLists
新增join
方法,因為它在實際的節點上沒有用:
// Returns "[object HTMLDivElement], [object HTMLDivElement] ..."
$$ ( '.child' ) . join ( ) ;
因此,您在映射屬性時仍然可以使用它:
// Returns "child,child,child,child,child,child,child,child,child,child"
$$ ( '.child' ) . className . join ( ) ;
// Returns true if passed Node is included in the NodeList
$$ ( 'body' ) . includes ( document . body ) ;
// Returns body element: <body>
$$ ( 'body' ) . find ( function ( el ) {
return el === el ;
} ) ;
// Returns 0
$$ ( 'body' ) . findIndex ( function ( el ) {
return el === el ;
} ) ;
將來可能會有與Array.prototype
的名稱相同的DOM
方法,或者您可能只想將NodeList
轉換為Array
因此您可以將其用作本機Array
:
asArray
屬性 $$ ( 'body' ) . asArray ; // returns Array
$$ ( 'body' ) . asArray . forEach ( function ( ) { ... } ) ; // uses native Array method therefore you cannot chain
好吧,現在如何處理具有獨特屬性的元素。與HTMLAnchorElement(s)
一樣,它們具有href
屬性,該屬性不是從HTMLElement
繼承的。本範例中沒有HTMLAnchorElements
,但您將如何處理它。
// Returns undefined because it's a unique property that every element does not inherit
$$ ( 'a' ) . href
// Returns an Array of href values
$$ ( 'a' ) . get ( 'href' ) ;
Get()
也可以用在屬性Array
:
// Returns an Array of the value of each node.style.color
$$ ( '.child' ) . style . get ( 'color' ) ;
// Sets the href property of each Node in NodeList
$$ ( 'a' ) . set ( 'href' , 'https://www.example.com/' ) ;
set()
只會在屬性未定義的Nodes
上設定屬性:
$$ ( 'div, a' ) . set ( 'href' , 'https://www.example.com/' ) ;
href
只會在<a>
元素上設置,而不會在<div>
上設置
set()
也可以用於屬性Array
:
// Sets each element's color to red and returns the Array of styles back
$$ ( '.child' ) . style . set ( 'color' , 'red' ) ;
您也可以設定多個屬性:
$$ ( '.child' ) . set ( {
textContent : 'Hello World' ,
className : 'class1 class2'
} ) ;
與映射屬性相同:
$$ ( '.child' ) . style . set ( {
color : 'red' ,
background : 'black'
} ) ;
請記住,您可以連結:
$$ ( '.child' ) . set ( {
textContent : 'Hello World' ,
className : 'class1 class2'
} ) . style . set ( {
color : 'red' ,
background : 'black'
} ) ;
有些方法對於某些元素來說是獨特的。這就是您呼叫這些方法的方式:
$$ ( 'video' ) . call ( 'pause' ) ;
或者您可以循環遍歷元素並調用方法
傳遞參數怎麼樣:
// Returns Array of `CanvasRenderingContext2D`
$$ ( 'canvas' ) . call ( 'getContext' , '2d' ) ;
如果對任何元素呼叫的方法傳回某些內容,則將從call()
傳回這些傳回項目的Array
,否則將傳回NodeList
以允許方法連結。
瀏覽器的本機item(index)
方法與NodeList[index]
相同,但在我的方法中,它傳回該Node
作為我的NodeList
(如果您了解jQuery
它與 jQuery 的eq()
方法相同)
// returns the <html> element
$$ ( 'html, body' ) [ 0 ] ;
// returns my NodeList [<html>]
$$ ( 'html, body' ) . item ( 0 ) ;
這樣您就可以繼續使用我的 NodeList 的相同屬性/方法,而不必slice
出一個Node
owner
財產:所有所有者屬性所做的就是傳回屬性對應的NodeList
:
var elms = $$ ( '.child' ) ;
elms . style . owner === elms ; // true
所以我可以做各種各樣的事情:
請記住映射style
回傳CSSStyleDeclarations
Array
$$ ( '.child' ) . style ;
這將為您傳回映射style
的NodeList
:
var childs = $$ ( '.child' ) ;
childs . style . owner === childs ; // true
如果你了解jQuery
它與它的prevObj
屬性相同
$$ . NL . myMethod = function ( ) {
// You'll have to write your own loop here if you want to call this on each Node or use:
this . forEach ( function ( node ) {
// do something with each node
} ) ;
}
瀏覽器 | 版本 |
---|---|
火狐 | 6+ |
狩獵之旅 | 5.0.5+ |
鉻合金 | 6+ |
IE | 9+ |
歌劇 | 11+ |
注意:你必須意識到我的庫依賴它正在運行的瀏覽器(這很棒,因此當瀏覽器使用新屬性/方法更新DOM
時它會自動更新)意味著:假設瀏覽器中不存在hidden
屬性DOM
API 你不能這樣做: $$('.child').hidden = true;