2016-02-05 118 views
0

我想在我的代碼中重複少。在我的一些有許多元素的代碼中,我覺得我做得太多了。我該學習如何減少代碼並遵循DRY技術。ForEach功能與事件監聽器

下面的代碼是我目前如何將eventListeners附加到我的元素。

var at1, at2 ,at3 ,at4 ,at5 ,at6 , at7, at8, 

at1 = UI.byId("at1"); 
at1.addEventListener("click", UI.at1Func, false); 

at2 = UI.byId("at2"); 
at2.addEventListener("click", UI.at2Func, false); 

at3 = UI.byId("at3"); 
at3.addEventListener("click", UI.at3Func, false); 

at4 = UI.byId("at4"); 
at4.addEventListener("click", UI.at4Func, false); 

at5 = UI.byId("at5"); 
at5.addEventListener("click", UI.at5Func, false); 

at6 = UI.byId("at6"); 
at6.addEventListener("click", UI.at6Func, false); 

at7 = UI.byId("at7"); 
at7.addEventListener("click", UI.at7Func, false); 

at8 = UI.byId("at8"); 
at8.addEventListener("click", UI.at8Func, false); 

我一直在嘗試使用forEach循環。但我有這個功能的問題。對於初學者來說,功能似乎正在被搶先引發。而且因爲我期望我的主要負載能夠反映出任何變化,它會造成無限循環和崩潰。我正在使用VS2015,並且我嘗試使用普通的JS編寫而沒有任何庫...請不要jquery。

這是我在forEach循環中的嘗試:請參閱底部的編輯。

var ats = ['at1', 'at2', 'at3', 'at4', 'at5', 'at6', 'at7', 'at8']; 
     ats.forEach(function (key) { 
      var ele = UI.byId(key); 
      ele.addEventListener("click", UI.atFunc(key), false); 
     }); 

該函數在我的「UI.myLoad」代碼塊中。這裏是UI.atFunc(鍵)...

atFunc: function (key) { 
    var value = localStorage.getItem(key); 
     localStorage.setItem(key, value++); 
     console.log(key); 
     //UI.myLoad(); //commented out to prevent crashing for now. 
    }, 

預期的行爲是被點擊任意鍵時,1個整數的值應該被添加到本地存儲的角度看項目,UI.myLoad剛加載應用程序的主要主題,值和超時。但是因爲我的forLoop在該代碼塊中,所以會導致崩潰。我把它移到了UI.myLoad的範圍之外,但是它根本不起作用。代碼有問題嗎?還是我想這是錯誤的方式,應該嘗試只使用for循環?我見過forEach可以正常工作的例子,但我不能自己做對。

[編輯:下面的代碼是一個解決方案,使用接受的答案,但發現了另一個問題。將完整的解決方案現在已經確定]

(function() { 
var UI; 
UI = { 
byId: function (id) { 
     return document.getElementById(id); 
}, 
loadBtns: function() { 
    var ats = ['at1', 'at2', 'at3', 'at4', 'at5', 'at6', 'at7', 'at8']; 
    ats.forEach(function (key) { 
     var ele = UI.byId(key); 
     ele.addEventListener("click", UI.atFunc(key), false); 
    }); 
}, 
myLoad: function() { 
    //load and refresh elements 
    /* 
    var at1 = localStorage.getItem("at1"); 
     if (!at1) { 
      spn1.innerText = 0;    
     } 
     if (at1) { 
      spn1.innerText = at1; 
     } 
    .... 
    */ 
}, 
atFunc: function (key) { 
     return function() { 
      var value = localStorage.getItem(key); 
      localStorage.setItem(key, +value + +1); 
      UI.myLoad(); 
      }; 
    } 
} 
window.onload = function() { 
    UI.myLoad(); 
    UI.loadBtns(); 
} 
}()) 
+0

你想要的功能附加到它,不運行它立即。從'atFunc'返回一個新的函數。 –

+0

我做了一個編輯,但函數返回的是指數 – MrEhawk82

回答

1

您的問題,從atFunc莖。它「被搶先觸發」的原因是因爲你立即調用該函數。

ele.addEventListener("click", UI.atFunc(key), false); 

這樣做是運行函數UI.atFunc然後返回undefined值。這基本上會將您上面一行到:

UI.atFunc(key); 
ele.addEventListener("click", undefined, false); 

相反,你要捕捉正確的鍵的功能。由於功能就像在JS其他任何值,你可以返回一個這樣的:

atFunc: function(key) { 
    return function() { 
    var value = localStorage.getItem(key); 
    ... 
    }; 
} 

這樣你返回一個新的函數值,而不是一個undefined的和函數綁定到click事件。

+0

我必須做別的事情不對,它仍然會多次觸發。我將在上面進行編輯。 – MrEhawk82

+1

我標記了這個答案,因爲這是如何解決最初的問題。然而,當我在我的代碼中使用這個解決方案(以及其他答案)時,函數被稱爲指數。我通過將我的事件偵聽器移到myLoad函數之外並將其分別加載到我的對象中來解決該問題。 – MrEhawk82

0

問題是函數被添加到addEventListener中的方式。

在第一個代碼,你正確地引用功能

at1.addEventListener("click", UI.at1Func, false); 

但在第二個代碼,您已經添加了括號,括號和調用函數馬上返回結果,這將是undefined

有很多方法來解決這個問題,但可能在你的情況下,最簡單的是修改atFunc功能具有關閉並返回一個函數

atFunc: function (key) { 
    return function() { 
     localStorage[key]++; 
    } 
},