NodeList.js
使用すると、 Nodes
のArray
でネイティブ DOM API をjQuery
と同じくらい簡単に使用できるようになり、約4k minifiedと非常に小さいという利点があり、ブラウザーが依存関係になります(これが最も興味深い部分です) 。
最初に気づくのは、 $$
を使用していることです。DOM 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
ではなく、別名 my NodeList
) を返します。
// Method 1
$$ ( '#container div' ) ;
// Method 2
$$ ( '#container' ) . children ;
// Method 3
$$ ( 'div div' ) ;
クエリ文字列を渡す場合、スコープとして渡すことができる 2 番目の引数があります。
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
、またはNode
、 NodeList
、 HTMLCollections
以外のものを含むArray of Arrays
はないものを渡すと、 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 ) ;
#container となる最初の要素を document.body に置き換えましょう。
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 メソッドと同じ名前のDOM
メソッドが登場する可能性があります。あるいは、単にNodeList
Array
に変換してネイティブArray
として使用できるようにしたい場合もあります。
asArray
プロパティ $$ ( 'body' ) . asArray ; // returns Array
$$ ( 'body' ) . asArray . forEach ( function ( ) { ... } ) ; // uses native Array method therefore you cannot chain
さて、固有のプロパティを持つ要素を扱うのはどうなるでしょうか。 HTMLAnchorElement(s)
HTMLElement
から継承されないhref
プロパティがあります。この例には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' ) ;
いずれかの要素で呼び出されたメソッドが何かを返す場合、それらの返された項目のArray
がcall()
から返されます。それ以外の場合は、メソッド チェーンを可能にするために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 ) ;
これは、1 つのNode
slice
のではなく、NodeList の同じプロパティ/メソッドを使用し続けることができるようにするためです。
owner
プロパティ: 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;