NodeList.js使得在Nodes Array上使用本机 DOM API就像jQuery一样简单,其优点是它非常小,大约4k 缩小,并且浏览器作为依赖项(这是最有趣的部分) 。
您会注意到的第一件事是我使用$$ ,我选择它来选择DOM Nodes的原因是因为如果您打开开发工具并输入以下内容:
$$ ( 'div' ) ; // Will return a NodeListNodeList.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;