2017-05-30 103 views
1

我需要向8个对象(手掌)添加一些侦听器。 这些对象是相同的,但行为必须根据其位置进行更改。 我有如下(丑陋的)代码:需要参数的addEventListener(和removeEventListener)函数

root.palmsStatus = ["B","B","B","B","B","B","B","B"]; 

if (root.palmsStatus[0] !== "N") 
    root.game.palms.palm1.addEventListener("click", palmHandler = function(){ palmShakeHandler(1); }); 
if (root.palmsStatus[1] !== "N") 
    root.game.palms.palm2.addEventListener("click", palmHandler = function(){ palmShakeHandler(2); }); 
if (root.palmsStatus[2] !== "N") 
    root.game.palms.palm3.addEventListener("click", function(){ palmShakeHandler(3); }); 
if (root.palmsStatus[3] !== "N") 
    root.game.palms.palm4.addEventListener("click", function(){ palmShakeHandler(4); }); 
if (root.palmsStatus[4] !== "N") 
    root.game.palms.palm5.addEventListener("click", function(){ palmShakeHandler(5); }); 
if (root.palmsStatus[5] !== "N") 
    root.game.palms.palm6.addEventListener("click", function(){ palmShakeHandler(6); }); 
if (root.palmsStatus[6] !== "N") 
    root.game.palms.palm7.addEventListener("click", function(){ palmShakeHandler(7); }); 
if (root.palmsStatus[7] !== "N") 
    root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); }); 

我有两个要求:

1)不使用的点击事件的匿名函数。

我写了这个代码,但它不工作

root.game.palms.palm8.addEventListener("click", palmShakeHandler(8)); 

所以这一块工作正常

root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); }); 

但我不知道如何删除事件侦听器。 我尝试此解决方案,但它不工作

root.game.palms.palm8.addEventListener("click", palmHandler = function(){ palmShakeHandler(8); }); 
root.game.palms.palm8.removeEventListener("click", palmHandler); 

2)添加和删除监听器在用于循环

我写了如下代码,但该行为是不正确的。加入

for (i=1; i <= root.palmsStatus.length; i++){ 
    if (root.palmsStatus[i-1] !== "N"){ 
     root.game.palms["palm" + i].addEventListener("click", function(){ palmShakeHandler(i); }); 
    } 
    } 

听众,但传递给palmShakeHandler参数的值总是8.

没有人能帮助我解决这些问题?

回答

4

在JavaScript中使用Function.prototype.bind方法有一个实际的,完美的方法。

bind让您定义将作为参数传递的函数的额外参数。

您还应该记住bind会创建一个新函数并且不会修改初始函数。

这里是什么样子:

function palmHandler(number) { 
    // your code working with `number` 
} 

var palmHandler8 = palmHandler.bind(null, 8) 
// the palmHandler8 is now tied to the value 8. 
// the first argument (here null) define what `this` is bound to in this function 

这应该可以解决你的问题,你就可以轻松移除处理程序:)

您的代码将是这样的:

for (i=1; i <= root.palmsStatus.length; i++){ 
    if (root.palmsStatus[i-1] !== "N"){ 
    root.game.palms["palm" + i].addEventListener("click", palmShakeHandler.bind(null, i)); 
    } 
} 

为了能够随后删除处理程序,您需要保留对您使用bind创建的函数的引用。这将是做到这一点的方式。

var boundHandler = handler.bind(null, i); 
element.addEventListener(boundHandler); 
element.removeEventListener(bounderHander); 

如果您想了解更多关于JavaScript中的真棒bind法,MDN是你的朋友:) https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

顺便说一句,你函数总是返回8是JavaScript的一个非常普遍的问题,这个问题。这个线程将解释所有的东西(扰流,这是一个范围:))https://stackoverflow.com/a/750506/2745879

+0

将监听程序添加到循环中很好。 但删除它们不起作用 – Zauker

+0

我使用此代码: root.game.palms [“palm”+ palm] .removeEventListener(“click”,palmShakeHandler); – Zauker

+0

噢,要删除处理程序,您需要保留对绑定函数的引用并删除该函数。 'var boundPalm = palm.bind(null,i); addHandler(boundPalm)... removeHandler(boundPalm)' – atomrc

0

在你最后的解决方案中,你正在为每个函数设置相同的变量,这就是使函数与8一起工作的原因,因为它是最后一个值的变量。

要工作arround,你可以使用“让”(请至少使用VAR,otherside,“我”是全球性的,可以在代码中的每个地方进行更改),但由于我不知道你的目标是什么,我建议其他解。

for (var i=1; i <= root.palmsStatus.length; i++){ 
    if (root.palmsStatus[i-1] !== "N"){ 
     root.game.palms["palm" + i].addEventListener("click", (function(index) 
     (return function(){ 
     palmShakeHandler(index); 
     }))(i); 
    } 
    } 

由于它看起来像你是针对现代浏览器,我会用let。 https://kangax.github.io/compat-table/es6/

for (var i=1; i <= root.palmsStatus.length; i++){ 
    let index = i; 
    let intermediateFunction = function(){palmShakeHandler(index);}; 
    if (root.palmsStatus[i-1] !== "N"){ 
     root.game.palms["palm" + i].addEventListener("click",intermediateFunction); 
     root.game.palms["palm" + i].removeHandShake = function(){this.removeEventListener("click",intermediateFunction)}; 
    } 
    } 

所以,现在你只需要调用“removeHandShake”,将删除监听,

我有这个代码就在这里,因此缓解了一些小错误,弹出

+0

这似乎是一个很好的解决方案,但我不明白如何删除监听器添加。 – Zauker

+0

好,因为你需要做的removeEventListener你需要将它存储在某处的函数引用,我建议使用闭包。让我更新最佳答案 –

0

所以,如果你的“棕榈树”的阵列非常庞大,将单个事件监听器添加到每个监听器中基本上是一个糟糕的想法,因为这会导致性能缺陷。所以我会建议一个不同的方法:

var handlers = [function (e) {}, …, function (e) {}]; 

root.game.palms.forEach(functiion (palm, idx) { 
    palm.setAttribute('data-idx', idx); 
}); 

<palmsparent>.addEventListener('click', function (e) { 
    var c = e.target, idx = -1; 

    while (c) { 
    if (c.hasAttribute && c.hasAttribute('data-idx')) { 
     idx = parseInt(c.getAttribute('data-idx')); 
     break; 
    } 
    c = c.parentNode; 
    } 

    //here you also check for the »palm status« 
    if (idx >= 0) { 
    handlers[idx](c); 
    } 
}) 

所有的事件监听器,更容易移除和更好的性能。

相关问题