在jQuery中,我們有一個功能,每一個這樣的什麼是JavaScript中jQuery的each()函數的替代品?
$('button').each(function(i) {
$('button').eq(i).css('background', 'red');
});
我們如何能夠用普通的JavaScript將這段代碼?
在jQuery中,我們有一個功能,每一個這樣的什麼是JavaScript中jQuery的each()函數的替代品?
$('button').each(function(i) {
$('button').eq(i).css('background', 'red');
});
我們如何能夠用普通的JavaScript將這段代碼?
與querySelectorAll()
瀏覽器的DOM的選擇有多種選擇方式,從DOM元素,但也許是最靈活和方便的是querySelectorAll
。它允許您使用CSS樣式選擇器來獲取給定根目錄中的所有匹配元素。
在你的情況下,它應該是這樣的:
document.querySelectorAll("button");
縮短querySelectorAll()
很美妙,那就是,這是一個有點冗長,所以它並不少見創建縮短它的包裝功能。這就是我們在這裏要做的,名字爲Q
。
function Q(root, selector) {
if (typeof root === "string") {
selector = root
root = document
}
return root.querySelectorAll(selector)
}
第一個參數是您從中進行選擇的上下文,第二個參數是選擇器。如果你只傳遞一個字符串,它將使用document
作爲上下文。
所以,現在你的DOM的選擇會是這樣,我們將在以後使用:
Q("button");
借款Array.prototype.forEach
一個很常見的方式做一個功能的循環結構是借用Array.prototype
的forEach
方法,並使用函數的在元素集合上調用它方法是這樣的:
Array.prototype.forEach.call(Q("buttons"), function(el) {
el.style.background = "red";
});
或者在最現代的瀏覽器,我們可以用箭頭的功能,縮短了一點:
Array.prototype.forEach.call(Q("buttons"), el => el.style.background = "red");
綁定和緩存借用.forEach()
.forEach()
借用可以縮短d如果在應用程序的早期階段,使用函數原型的bind()
方法將.forEach()
方法綁定到的值.call()
。
const each = Function.call.bind(Array.prototype.forEach);
這樣你就可以把它稱爲接收元素集合作爲第一個參數的函數。
each(Q("button"), function(el) {
el.style.background = "red";
});
再或者在一些最新的瀏覽器的使用中的箭頭功能:
each(Q("button"), el => el.style.background = "red");
使用Array.from()
的Array.from
方法還介紹可以輕鬆地轉換陣列類似的對象到實際的數組中。這可讓您直接使用.forEach()
,並且可以使用簡單的polyfill (請參閱文檔鏈接)將其修補到傳統瀏覽器中。
Array.from(Q("button")).forEach(function(el) {
el.style.background = "red";
});
如果直接把Array.from
呼叫我們Q
功能上面,你就可以直接調用.forEach()
。
Q("button").forEach(function(el) {
el.style.background = "red";
});
使用for-of
循環
在最新的瀏覽器,你可以使用一個for-of
loop代替,使得一切都非常短,乾淨:
for (const el of Q("button")) {
el.style.background = "red";
}
這樣沒有必要轉換爲Array
或使用.forEach
。
Transpiling現代代碼
對於上面的例子中需要最現代的瀏覽器,可有transpilers(例如Babel),將翻譯的最新標準成代碼,將工作中舊版瀏覽器。
創建自定義each()
作爲一個側面說明,如果你想this
來指代當前元素,或任何其他特定的行爲,這是一個基本each
實現,收到回收和回調。
function each(a, callback) {
for (var i = 0; i < a.length; i++) {
callback.call(a[i], a[i], i, a);
}
}
雖然以這種方式使用this
通常不需要,因爲你已經擁有的元素作爲參數。
不錯。但在jQuery的'$(...)。each()'中,'this'將指向元素。 – haim770
@ haim770:的確如此,儘管我認爲OP只是想知道如何在JS中做這樣的循環,而不一定完全按照它在jQuery中的表現。 – 2016-11-28 21:17:05
@squint你爲什麼使這是一個CW? –
var buttons = document.querySelectorAll("button");
for(var x in buttons){
var e = buttons[x];
e.innerHTML="stuff";
}
as squint指出,它應該是buttons [x]和var x。 對不起。
哎呀忘了關於e =按鈕[x] – MyNameIsUser9123
您可以使用函數getElementsByTagName()
查詢DOM以查找某個標記的元素並返回元素集合。您可以在document
上調用此函數,或者您可以更具體一些,並使用document.getElementById()
選擇一個元素,然後在該元素內查找標記。
無論哪種方式,一旦你有一個元素的集合,你可以循環集合並相應地應用樣式。
//query the document for all <button> elements
var buttons = document.getElementsByTagName('button');
/* -- OR -- */
//query the document for all buttons inside of a specific element
var container = document.getElementById('container');
var buttons = container.getElementsByTagName('button');
//loop over the collection of buttons and set each background to 'red'
for(var i=0; i<buttons.length; i++) {
buttons[i].style.background = "red";
}
編輯:我意識到這不是jQuery的每個函數的工作原理。 OP沒有說明他想特別地看到,只是一種用JS完成$.each()
功能的方法(因爲有很多可能性)。這個例子只是一個使用非常基本概念的簡單方法。
受更多瀏覽器支持,因爲它不使用forEach
。
如果使用getElementsByTagName
,請將函數添加到HTMLCollection
。
HTMLCollection.prototype.each = function(callback){
for(var i=0; i<this.length; i++) callback(this[i]);
};
document.getElementsByTagName('div').each(function(div){
div.innerHTML = "poo";
});
如果使用querySelectorAll
您可以將相同的功能NodeList
NodeList.prototype.each = function(callback){
for(var i=0; i<this.length; i++) callback(this[i]);
};
document.querySelectorAll('div').each(function(div){
div.innerHTML = "podo";
});
爲安撫chanters(見註釋),我會規定,如果這是你寫一個庫,或者如果將它與可能覆蓋它的庫一起使用,顯然你會想考慮其他方法。
[不要修改你不擁有的對象。](http://stackoverflow.com/q/6223449/3853934) –
@Gothdo不要做一攬子聲明,只適用於某些情況下,否則根本沒有意義。 –
如果您認爲這不適用於您的情況,請解釋。 –
但你也在你的榜樣可疑的方式使用$.each()
。使用this
訪問元素更容易,更快速。
$('button').each(function(i) {
$(this).css('background', 'red');
});
最簡單的替換就是使用簡單的函數閉包,但它並不漂亮。
var $buttons = $('button');
for(var i = 0; i < $buttons.length; i++){
(function(i){
$buttons.eq(i).css('background', 'red');
})(i);
}
,或者設置this
使用.call()
調用功能。
var $buttons = $('button');
for(var i = 0; i < $buttons.length; i++){
(function(i){
$(this).css('background', 'red');
}).call($buttons[i], i);
}
在第二個例子中實際上並不需要IIFE,因爲在循環中立即使用'i',而不是稍後在回調中使用。儘管你對OP的技術是正確的。在循環中反覆調用'$('按鈕')'會很慢。 – 2016-11-29 13:22:27
@squint你是對的。但我已經擴展了「Michael Hamilton」的答案,目的是表明雖然結果相同,但它不是取代'.each()'的正確方法。 – Bizniztime
那麼'Array.prototype.forEach()',但它本身並不能代替*那*代碼。 – Pointy
只需使用'for ... of'循環。 – Bergi