NodeList.js
macht die Verwendung der nativen DOM-APIs auf einem Array
von Nodes
so einfach wie jQuery
, mit dem Vorteil, dass es mit etwa 4 KB verkleinert extrem klein ist und der Browser eine Abhängigkeit darstellt (das ist der interessanteste Teil) .
Das Erste, was Ihnen auffallen wird, ist, dass ich $$
verwende. Der Grund, warum ich dies für die Auswahl DOM Nodes
ausgewählt habe, liegt darin, dass Sie Ihre Devtools öffnen und Folgendes eingeben:
$$ ( 'div' ) ; // Will return a NodeList
NodeList.js
-Nutzung: HTML
bearbeiten wir im Folgenden: < 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
: Jedes der folgenden Elemente gibt ein Array of Nodes
zurück (auch bekannt als meine NodeList
, nicht die native NodeList
des Browsers).
// Method 1
$$ ( '#container div' ) ;
// Method 2
$$ ( '#container' ) . children ;
// Method 3
$$ ( 'div div' ) ;
Wenn Sie eine Abfragezeichenfolge übergeben, gibt es ein zweites Argument, das Sie als Bereich übergeben können:
let container = document . getElementById ( 'container' ) ;
$$ ( 'div' , container ) ;
Was äquivalent wäre zu:
// Just this doesn't return my NodeList, but the browser's NodeList
container . querySelectorAll ( 'div' ) ;
Sie können Knoten als Argumente übergeben:
$$(document, document.body); // returns NodeList
Sie können auch 1 Array
von Knoten oder eine NodeList
oder eine HTMLCollection
übergeben . Wird nicht reduziert, zum Flattern verwenden Sie concat()
:
$$([document, document.body]); // returns NodeList
Node
abrufen :So würden Sie es normalerweise tun:
let children = document . getElementsByClassName ( 'child' ) ;
Jetzt würden Sie Eigenschaften für die untergeordneten Elemente des #container
erhalten:
for ( let i = 0 , l = children . length ; i < l ; i ++ ) {
children [ i ] . id ; // ''
children [ i ] . nodeName ; // 'DIV'
children [ i ] . className ; // 'child'
}
So würden Sie es mit nodeList.js
machen:
$$ ( '.child' ) . id ; // ['', '' ... x10]
$$ ( '.child' ) . nodeName ; // ['DIV', 'DIV' ... x10]
$$ ( '.child' ) . className ; // ['child', 'child' ... x10]
Daher würden Sie jede Eigenschaft genauso lesen, wie Sie es mit einem einzelnen Node
tun würden :)
Beachten Sie , dass ein Array
des Werts der Eigenschaft zurückgegeben wird. Das heißt, Sie können sie anhand des index
auswählen und beliebige Array Methods
darauf verwenden. Sie werden sehen, wenn Sie zum Schleifenteil gelangen.
node
festlegen : Lassen Sie uns weiterhin die Variable children
verwenden. So würden Sie also Eigenschaften für die children
festlegen:
for ( let i = 0 , l = children . length ; i < l ; i ++ ) {
children [ i ] . className = 'containerChild' ;
children [ i ] . textContent = 'This is some text' ;
}
So würden Sie es mit NodeList.js
machen:
$$ ( '.child' ) . className = 'containerChild' ;
$$ ( '.child' ) . textContent = 'This is some text' ;
node
: Ich verwende immer noch die Variable children
:
Fügen wir jedem Knoten einen Ereignis-Listener hinzu, auch wenn event delegation
am besten wäre, aber für dieses Beispiel:
for ( let i = 0 , l = children . length ; i < l ; i ++ ) {
children [ i ] . addEventListener ( 'click' , function ( ) {
console . log ( this , 'was clicked' ) ;
} ) ;
}
So würden Sie es mit NodeList.js
machen:
$$ ( '.child' ) . addEventListener ( 'click' , function ( ) {
console . log ( this , 'was clicked' ) ;
} ) ;
So cool, oder? Sie können jede Native DOM method
verwenden:
Lassen Sie uns einige Attribute festlegen:
$$ ( '.child' ) . setAttribute ( 'class' , 'child div' ) ;
// For setting the class you could just do:
$$ ( '.child' ) . className = 'child div' ;
Anklicken der Elemente:
$$ ( '.child' ) . click ( ) ;
Entfernen der Elemente:
$$ ( '.child' ) . remove ( ) ;
Ich denke, Sie verstehen, worum es geht: Jede Native DOM Method
, die jeder Node/Element
erbt, können Sie einfach auf der NodeList
aufrufen, und sie wird für jedes Element aufgerufen.
Übrigens: Alle DOM
Methoden, die normalerweise undefined
zurückgeben würden, wenn sie auf einem einzelnen Node
aufgerufen werden, geben dieselbe NodeList
zurück, um eine Methodenverkettung zu ermöglichen. Wie setAttribute()
.
Verwenden einer for-Schleife und ES6
for-of
:
Wir werden nur als Beispiele die Knoten aus dem DOM
entfernen:
let nodes = $$ ( '.child' ) ;
for ( let i = 0 , l = nodes . length ; i < l ; i ++ ) {
nodes [ i ] . remove ( ) ;
}
for ( let node of nodes ) {
node . remove ( ) ;
}
Verwendung von forEach
:
// Removes all Nodes and returns same the NodeList to allow method chaining
$$ ( '.child' ) . forEach ( function ( node ) {
node . remove ( ) ;
} ) ;
// But Just do:
$$ ( '.child' ) . remove ( ) ;
Durchlaufen der Eigenschaften:
// 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 ) ;
Die Zuordnung ist einfach. Rufen Sie einfach die Eigenschaft ab, genau wie bei einem einzelnen Knoten
// 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' ) ;
} ) ;
Ich könnte mir kein besseres Beispiel für die Verwendung von Reduce auf einer NodeList vorstellen (aber es ist möglich).
let unique = $$ ( 'div' ) . reduce ( function ( set , div ) {
set . add ( div . parentElement ) ;
return set ;
} , new Set ( ) ) ;
Es gibt auch reduceRight()
Die folgenden concat()
-Methoden geben alle eine neue verkettete NodeList
zurück (keine Auswirkungen auf die NodeList
für die concat()
aufgerufen wird)
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()
ist rekursiv, sodass Sie ein Array
mit der gewünschten Tiefe übergeben können.
Wenn Sie nun etwas übergeben, das kein Node
, NodeList
, HTMLCollections
, Array
oder tiefes Array of Arrays
ist und etwas anderes als Node
, NodeList
, HTMLCollections
oder Array
enthält, wird ein Error
ausgegeben .
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()
benötigt ein optionales Argument dafür, wie viele Nodes
POP sein sollen
// 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()
benötigt außerdem ein optionales Argument dafür, wie viele Nodes
verschoben werden sollen
// 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 ) ;
Ersetzen wir das erste Element, das #container wäre, durch 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 ( ) ;
Ich habe keine join
-Methode für NodeLists
hinzugefügt, da diese auf den tatsächlichen Knoten nutzlos wäre:
// Returns "[object HTMLDivElement], [object HTMLDivElement] ..."
$$ ( '.child' ) . join ( ) ;
Daher können Sie es beim Zuordnen von Eigenschaften weiterhin verwenden:
// 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 ;
} ) ;
Möglicherweise wird es in Zukunft DOM
-Methoden geben, die denselben Namen wie die von Array.prototype
haben, oder Sie möchten die NodeList
einfach in ein Array
konvertieren, damit Sie sie als natives Array
verwenden können :
asArray
Eigenschaft $$ ( 'body' ) . asArray ; // returns Array
$$ ( 'body' ) . asArray . forEach ( function ( ) { ... } ) ; // uses native Array method therefore you cannot chain
Ok, wie wäre es nun mit dem Umgang mit Elementen, die einzigartige Eigenschaften haben? Wie HTMLAnchorElement(s)
verfügen sie über die href
Eigenschaft, die nicht von HTMLElement
geerbt wird. In diesem Beispiel gibt es keine HTMLAnchorElements
, aber hier erfahren Sie, wie Sie damit umgehen.
// 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()
kann auch für ein Array
von Eigenschaften verwendet werden:
// 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()
legt nur die Eigenschaften der Nodes
fest, deren Eigenschaften nicht undefiniert sind:
$$ ( 'div, a' ) . set ( 'href' , 'https://www.example.com/' ) ;
href
wird nur für die <a>
-Elemente und nicht für die <div>
-Elemente festgelegt
set()
kann auch für ein Array
von Eigenschaften verwendet werden:
// Sets each element's color to red and returns the Array of styles back
$$ ( '.child' ) . style . set ( 'color' , 'red' ) ;
Sie können auch mehrere Eigenschaften festlegen:
$$ ( '.child' ) . set ( {
textContent : 'Hello World' ,
className : 'class1 class2'
} ) ;
Das Gleiche gilt für zugeordnete Eigenschaften:
$$ ( '.child' ) . style . set ( {
color : 'red' ,
background : 'black'
} ) ;
Denken Sie daran, dass Sie Folgendes verketten können:
$$ ( '.child' ) . set ( {
textContent : 'Hello World' ,
className : 'class1 class2'
} ) . style . set ( {
color : 'red' ,
background : 'black'
} ) ;
Es gibt Methoden, die nur für bestimmte Elemente gelten. So würden Sie diese Methoden aufrufen:
$$ ( 'video' ) . call ( 'pause' ) ;
Oder Sie können einfach die Elemente durchlaufen und die Methoden aufrufen
Wie wäre es mit der Übergabe von Argumenten:
// Returns Array of `CanvasRenderingContext2D`
$$ ( 'canvas' ) . call ( 'getContext' , '2d' ) ;
Wenn die für eines der Elemente aufgerufene Methode etwas zurückgibt, wird von call()
ein Array
dieser zurückgegebenen Elemente zurückgegeben, andernfalls wird die NodeList
zurückgegeben, um eine Methodenverkettung zu ermöglichen.
Die native item(index)
-Methode des Browsers macht dasselbe wie NodeList[index]
aber in meinem gibt sie diesen Node
als meine NodeList
zurück (Wenn Sie jQuery
kennen, ist es dasselbe wie eq()
-Methode von jQuery)
// returns the <html> element
$$ ( 'html, body' ) [ 0 ] ;
// returns my NodeList [<html>]
$$ ( 'html, body' ) . item ( 0 ) ;
Auf diese Weise können Sie weiterhin dieselben Eigenschaften/Methoden meiner NodeList verwenden, anstatt den einen Node
slice
zu müssen
owner
: Die Eigentümereigenschaft gibt Ihnen lediglich die NodeList
zurück, aus der die Eigenschaft zugeordnet wurde:
var elms = $$ ( '.child' ) ;
elms . style . owner === elms ; // true
Damit ich alles Mögliche machen kann:
Denken Sie daran, dass style
Zuordnungsstil ein Array
von CSSStyleDeclarations
zurückgibt
$$ ( '.child' ) . style ;
Dadurch erhalten Sie die NodeList
zurück, aus der der style
zugeordnet wurde:
var childs = $$ ( '.child' ) ;
childs . style . owner === childs ; // true
Wenn Sie wissen, dass jQuery
mit seiner prevObj
-Eigenschaft identisch ist
$$ . 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
} ) ;
}
Browser | Version |
---|---|
FireFox | 6+ |
Safari | 5.0.5+ |
Chrom | 6+ |
IE | 9+ |
Oper | 11+ |
Achtung: Sie müssen sich darüber im Klaren sein, dass meine Bibliothek vom Browser abhängt, den sie ausführt (was großartig ist, da sie automatisch aktualisiert wird, wenn der Browser das DOM
mit neuen Eigenschaften/Methoden aktualisiert). Das heißt: Nehmen wir an, die hidden
Eigenschaft existiert im Browser nicht DOM
API ist nicht möglich: $$('.child').hidden = true;