NodeList.js
ทำให้การใช้ Native DOM API บน Array
of Nodes
เป็นเรื่องง่ายเหมือนกับ jQuery
โดยมีข้อดีคือมีขนาดเล็กมากที่ประมาณ 4k minified และเบราว์เซอร์เป็นการพึ่งพา (นั่นคือส่วนที่น่าสนใจที่สุด)
สิ่งแรกที่คุณจะสังเกตได้คือฉันใช้ $$
เหตุผลที่ฉันเลือกสิ่งนี้เพื่อเลือก DOM Nodes
ก็เพราะว่าถ้าคุณเปิด devtools ขึ้นมาแล้วพิมพ์ข้อความต่อไปนี้:
$$ ( '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
(AKA my 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
of Nodes หรือ 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 ( ) ;
ฉันคิดว่าคุณได้รับประเด็น: Native DOM Method
ใด ๆ ที่ทุก Node/Element
สืบทอดมาคุณสามารถเรียกใช้ NodeList
และมันจะถูกเรียกใช้ในแต่ละองค์ประกอบ
BTW: วิธีการ DOM
ทั้งหมดที่ปกติจะส่งคืน undefined
เมื่อถูกเรียกบน Node
เดียว จะส่งคืน NodeList
เดียวกัน กลับมาเพื่ออนุญาต Method Chaining เช่นเดียวกับ setAttribute()
การใช้ for loop และ 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 ได้ (แต่เป็นไปได้)
let unique = $$ ( 'div' ) . reduce ( function ( set , div ) {
set . add ( div . parentElement ) ;
return set ;
} , new Set ( ) ) ;
นอกจากนี้ยังมี reduceRight()
วิธี concat()
ต่อไปนี้ทั้งหมดส่งคืน NodeList
ที่ต่อกันใหม่ (ไม่ส่งผลกระทบต่อ NodeList
ที่ concat()
กำลังถูกเรียกใช้)
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
หรือ Deep 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()
รับอาร์กิวเมนต์ทางเลือกของจำนวน Nodes
ถึง POP
// 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()
ยังรับอาร์กิวเมนต์ที่เป็นตัวเลือกของจำนวน Nodes
ที่จะ SHIFT
// 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 ( ) ;
ฉันไม่ได้ใส่วิธี join
สำหรับ NodeLists
เพราะมันไม่มีประโยชน์กับโหนดจริง:
// 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 ;
} ) ;
อาจมีเมธอด DOM
ที่เป็นชื่อเดียวกับ Array.prototype
ในอนาคต หรือคุณอาจต้องการแปลง 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' ) ;
หากเมธอดที่ถูกเรียกใช้บนองค์ประกอบใดๆ ส่งคืนบางสิ่ง Array
ของรายการที่ส่งคืนเหล่านั้นจะถูกส่งคืนจาก call()
มิฉะนั้น NodeList
จะถูกส่งคืนเพื่อให้สามารถเชื่อมโยงเมธอดได้
วิธีการ item(index)
ของเบราว์เซอร์ทำเหมือนกับ NodeList[index]
แต่ในตัวฉันมันจะส่งคืน Node
นั้นว่าเป็น NodeList
ของฉัน (ถ้าคุณรู้ว่า jQuery
มันจะเหมือนกับวิธี eq()
ของ jQuery)
// 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
การแมปจะส่งคืน Array
ของ CSSStyleDeclarations
$$ ( '.child' ) . style ;
สิ่งนี้จะคืน NodeList
ให้คุณทราบว่า style
ใดถูกแมปจาก:
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+ |
เช่น | 9+ |
โอเปร่า | 11+ |
ข้อควรสนใจ: คุณต้องตระหนักว่าไลบรารี่ของฉันขึ้นอยู่กับเบราว์เซอร์ที่มันใช้งานอยู่ (ซึ่งยอดเยี่ยมมาก ดังนั้นมันจึงอัปเดตโดยอัตโนมัติเมื่อเบราว์เซอร์อัปเดต DOM
ด้วยคุณสมบัติ/วิธีการใหม่) ความหมาย: สมมติว่าคุณสมบัติ hidden
ไม่มีอยู่ในเบราว์เซอร์ DOM
API คุณไม่สามารถทำได้: $$('.child').hidden = true;