简体   繁体   English

具有事件侦听器的ForEach函数

[英]ForEach function with event listener

I am trying to repeat less in my code. 我试图在我的代码中减少重复。 In some of my codes that have many elements, I feel like i'm doing too much. 在我的一些包含很多元素的代码中,我觉得自己做得太多。 It's time I learned how to reduce code and follow DRY techniques. 是时候该学习如何减少代码并遵循DRY技术了。

The code below is how I am currently attaching eventListeners to my elements. 下面的代码是我当前如何将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);

I have been trying to use the forEach loop. 我一直在尝试使用forEach循环。 But i am having issues with the function. 但是我在功能上有问题。 For starters, it seems the function is being triggered preemptively. 对于初学者来说,该功能似乎是抢先触发的。 And because I expect the my main load to reflect any changes, it creates and infinite loop and crashes. 而且因为我希望我的主要负载能够反映出任何变化,所以它会造成无限循环并崩溃。 I am using VS2015, and i try to write using plain JS without any libraries... please, no jquery. 我正在使用VS2015,我尝试使用不带任何库的纯JS编写...请不要使用jquery。

Here is my attempt at the forEach loop: see edits at the bottom. 这是我对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);
        });

That function is in my "UI.myLoad" code block. 该函数在我的“ UI.myLoad”代码块中。 Here is UI.atFunc(key)... 这是UI.atFunc(key)...

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

the expected behavior is that when any key is clicked, the value of 1 integer should be added to its perspective item in local storage, and UI.myLoad just loads the main themes, values, and timeouts on the app. 预期的行为是,当单击任何键时,应将1整数的值添加到本地存储中的透视图项中,并且UI.myLoad只会在应用程序上加载主要主题,值和超时。 But because my forLoop is in that code block, it is causing a crash. 但是因为我的forLoop在该代码块中,所以导致崩溃。 I moved it outside of the scope on UI.myLoad, but then it didn't work at all. 我将其移至UI.myLoad范围之外,但随后根本不起作用。 Is there something wrong with the code? 代码有问题吗? or am i going about this the wrong way and should attempt to just use a for loop instead? 还是我会以错误的方式进行操作,应该尝试仅使用for循环? I've seen examples of the forEach working properly but i can't do it right myself. 我已经看到了forEach正常运行的示例,但我自己做不到。

[edit: The code below is a solution that used the accepted answer, but found another problem. [编辑:以下代码是使用了已接受答案的解决方案,但发现了另一个问题。 The full solution is now identified.] 现在确定了完整的解决方案。]

(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();
}
}())

Your problem stems from atFunc . 您的问题源于atFunc The reason it's "being triggered preemptively" is because you're immediately calling the function. 它“被抢先触发”的原因是因为您正在立即调用该函数。

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

What this does is runs the function UI.atFunc then returns the value of undefined . 这样做是运行函数UI.atFunc然后返回undefined的值。 This basically translates your above line into: 这基本上可以将您的上述代码转换为:

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

Instead, you want to return a function which captures the correct key. 相反,您想返回一个捕获正确键的函数。 Since functions are just like any other value in JS, you can return one like this: 由于函数与JS中的任何其他值一样,因此您可以返回以下内容:

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

This way you return a new function value instead of a undefined and that function is bound to the click event. 这样,您将返回一个新的函数值而不是undefined值,并且该函数绑定到click事件。

The issue is the way the function is added in addEventListener . 问题是在addEventListener添加函数的方式。

In the first code, you correctly reference the function 在第一个代码中,您正确地引用了该函数

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

But in the second code, you've added parentheses, and parentheses calls the function right away and returns the result, which would be undefined . 但是在第二个代码中,您添加了括号,并且括号立即调用了该函数并返回结果,该结果将是undefined

There are many ways to solve this, but probably the easiest in your case would be to modify the atFunc function with a closure and return a function 有很多方法可以解决此问题,但是在您的情况下,最简单的方法可能是使用闭包修改atFunc函数并返回一个函数

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM