如何将参数传递给 addEventListener 监听器函数?

Posted

技术标签:

【中文标题】如何将参数传递给 addEventListener 监听器函数?【英文标题】:How to pass arguments to addEventListener listener function? 【发布时间】:2022-01-21 10:50:21 【问题描述】:

情况有点像-

var someVar = some_other_function();
someObj.addEventListener("click", function()
    some_function(someVar);
, false);

问题是someVar 的值在addEventListener 的侦听器函数中不可见,它可能被视为新变量。

【问题讨论】:

一篇很清楚的文章:toddmotto.com/avoiding-anonymous-javascript-functions 不是最干净的方式,但可以完成工作。请注意,如果 someVar 只能是数字或文本: eval('someObj.addEventListener("click",function()some_function('+someVar+'););'); 今天刚遇到这个问题 - 这里给出的解决方案是正确的(其他解决方案有 for 循环问题等问题) - ***.com/a/54731362/984471 【参考方案1】:

为什么不直接从事件的目标属性中获取参数?

例子:

const someInput = document.querySelector('button');
someInput.addEventListener('click', myFunc, false);
someInput.myParam = 'This is my parameter';
function myFunc(evt)

  window.alert(evt.currentTarget.myParam);
<button class="input">Show parameter</button>

JavaScript 是一种面向原型的语言,请记住!

【讨论】:

这是正确的答案,因为它让我们在'removeEventListener'函数之后使用。 不应该是evt.currentTarget.myParam吗?如果 'someInput' 内有另一个元素,evt.target 可能是指内部元素。 (jsfiddle.net/qp5zguay/1) 这会保留this!在 typescript 中使用此方法需要元素为 any 或创建子类型。 我的变量不断返回为未定义...关于如何解决这个问题的任何想法? 如果addEventListener 代表documentevt.target.myParam 对我不起作用。我不得不改用evt.currentTarget.myParam【参考方案2】:

您编写的代码绝对没有问题。 some_functionsomeVar 都应该是可访问的,以防它们在匿名的上下文中可用

function()  some_function(someVar);  

已创建。

检查警报是否为您提供了您一直在寻找的值,确保它可以在匿名函数的范围内访问(除非您有更多代码在调用旁边的同一 someVar 变量上运行addEventListener)

var someVar; 
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click", function()
    some_function(someVar);
, false);

【讨论】:

这在 for 循环中不起作用。我总是得到最新的值,而不是属于那个迭代的那个。有什么解决办法吗? 有人知道为什么它不能循环工作吗?这种行为的原因是什么? @Morfidon:在循环中, someVar 的值不是添加侦听器时的值,而是执行侦听器时的值。当监听器执行时,循环已经结束,所以 someVar 的值将是循环结束时的值。 这不是正确的答案,因为它不允许我们在之后使用'removeEventListener'函数。 @iMatoria 我刚刚发现使用.bind() 方法创建bound function 将解决循环问题developer.mozilla.org/en/docs/Web/JavaScript/Reference/…【参考方案3】:

这个问题很老,但我想我会提供一个使用 ES5 的.bind() 的替代方案 - 供后代使用。 :)

function some_func(otherFunc, ev) 
    // magic happens

someObj.addEventListener("click", some_func.bind(null, some_other_func), false);

请注意,您需要使用第一个参数作为您传递给 bind(您的另一个函数)的参数来设置您的侦听器函数,而第二个参数现在是事件(而不是第一个,因为它会已经)。

【讨论】:

Function.prototype.bind() 确实是解决此问题的最佳方法。此外,它在循环内直观地工作——你得到你想要的词法范围。没有匿名函数、IIFEs 或附加到对象的特殊属性。 看看IIFE vs bind()的优缺点。 使用Function.prototype.bind() 你不能remove the event listener,最好使用柯里化函数(见@tomcek112 答案) 注意:some_other_func 是一个变量,你可以将任何你想要的值传递给some_func【参考方案4】:

相当老的问题,但我今天遇到了同样的问题。我找到的最干净的解决方案是使用currying.的概念

代码:

someObj.addEventListener('click', some_function(someVar));

var some_function = function(someVar) 
    return function curried_func(e) 
        // do something here
    

通过命名 curried 函数,它允许您调用 Object.removeEventListener 以在稍后执行时取消注册 eventListener。

【讨论】:

很高兴遇到这个提到咖喱函数的答案。不过,您将如何删除事件侦听器? 看到好的术语真是太棒了。您应该能够通过命名 curried 函数来删除事件侦听器。我会提出修改建议。 这个答案将注册函数的次数与调用 addEventListener 的次数一样多,因为 some_function (var) 每次都返回一个新创建的函数。 我不喜欢必须命名 curried 函数以删除侦听器的想法,因为你需要处理 2 个你必须跟踪的差异命名空间 @martin36 注意暂存结构,你有一个currying function 和一个curried function。您应该添加和删除 currying 函数作为 evente 侦听器。在@tomeck112 的示例中,即some_function【参考方案5】:

您可以使用 'bind' 绑定所有必要的参数:

root.addEventListener('click', myPrettyHandler.bind(null, event, arg1, ... ));

通过这种方式,您将始终将eventarg1 和其他内容传递给myPrettyHandler

http://passy.svbtle.com/partial-application-in-javascript-using-bind

【讨论】:

谢谢!已经尝试过 .bind() 但没有 null 作为第一个参数。这没有用。 不需要null,它适用于.bind(event, arg1),至少适用于VueJS。【参考方案6】:

您可以通过将函数声明为变量来添加和删除带有参数的事件监听器。

myaudio.addEventListener('ended',funcName=function()newSrc(myaudio),false);

newSrc是以myaudio为参数的方法 funcName是函数名变量

你可以删除监听器 myaudio.removeEventListener('ended',func,false);

【讨论】:

【参考方案7】:

您可以通过称为 closure 的 JavaScript 功能按值(而不是通过引用)传递 somevar:

var someVar='origin';
func = function(v)
    console.log(v);

document.addEventListener('click',function(someVar)
   return function()func(someVar)
(someVar));
someVar='changed'

或者你可以写一个通用的换行函数,比如wrapEventCallback

function wrapEventCallback(callback)
    var args = Array.prototype.slice.call(arguments, 1);
    return function(e)
        callback.apply(this, args)
    

var someVar='origin';
func = function(v)
    console.log(v);

document.addEventListener('click',wrapEventCallback(func,someVar))
someVar='changed'

这里wrapEventCallback(func,var1,var2)就像:

func.bind(null, var1,var2)

【讨论】:

非常感谢您的回答! OP 不是在寻找这个,但我认为在谷歌中输入“如何将参数传递给 addEventListener”的人会寻找你的答案。它只是需要更多解释 :) 我正在编辑它。【参考方案8】:

不错的单行替代

element.addEventListener('dragstart',(evt) => onDragStart(param1, param2, param3, evt));
function onDragStart(param1, param2, param3, evt) 

 //some action...


【讨论】:

作为一个新的 JS 开发者,经过所有令人困惑的答案,我发现这个是最好的解决方案。谢谢!【参考方案9】:

Function.prototype.bind() 是将目标函数绑定到特定范围的方法,并可选择在目标函数中定义 this 对象。

someObj.addEventListener("click", some_function.bind(this), false);

或者捕获一些词法范围,例如在循环中:

someObj.addEventListener("click", some_function.bind(this, arg1, arg2), false);

最后,如果目标函数中不需要this参数:

someObj.addEventListener("click", some_function.bind(null, arg1, arg2), false);

【讨论】:

【参考方案10】:

这是另一种方式(这个在 for 循环中工作):

var someVar = some_other_function();
someObj.addEventListener("click", 

function(theVar)
    return function()some_function(theVar);
(someVar),

false);

【讨论】:

这是最好的方法。丑陋,但在循环中有效,因为通过将参数发送到匿名函数将捕获 var。【参考方案11】:

someVar 值只能在some_function() 上下文中访问,而不是从侦听器的上下文中访问。 如果您想在侦听器中使用它,则必须执行以下操作:

someObj.addEventListener("click",
                         function()
                             var newVar = someVar;
                             some_function(someVar);
                         ,
                         false);

改用newVar

另一种方法是从some_function() 返回someVar 值,以便在侦听器中进一步使用它(作为新的本地变量):

var someVar = some_function(someVar);

【讨论】:

【参考方案12】:

使用

   el.addEventListener('click',
    function()
        // this will give you the id value 
        alert(this.id);    
    ,
false);

如果你想将任何自定义值传递给这个匿名函数,那么最简单的方法就是

 // this will dynamically create property a property
 // you can create anything like el.<your  variable>
 el.myvalue = "hello world";
 el.addEventListener('click',
    function()
        //this will show you the myvalue 
        alert(el.myvalue);
        // this will give you the id value 
        alert(this.id);    
    ,
false);

在我的项目中完美运行。希望这会有所帮助

【讨论】:

是的,绝对有帮助,因为它还在 for 循环内保持了预期的范围。【参考方案13】:

如果我没记错的话,使用bind 调用函数实际上会创建一个由bind 方法返回的新函数。这将在以后给您带来问题,或者如果您想删除事件侦听器,因为它基本上就像一个匿名函数:

// Possible:
function myCallback()  /* code here */ 
someObject.addEventListener('event', myCallback);
someObject.removeEventListener('event', myCallback);

// Not Possible:
function myCallback()  /* code here */ 
someObject.addEventListener('event', function()  myCallback );
someObject.removeEventListener('event', /* can't remove anonymous function */);

请记住这一点。

如果您使用的是 ES6,您可以按照建议的方式进行操作,但更简洁:

someObject.addEventListener('event', () => myCallback(params));

【讨论】:

【参考方案14】:
    $form.addEventListener('submit', save.bind(null, data, keyword, $name.value, myStemComment));
    function save(data, keyword, name, comment, event) 

这就是我正确传递事件的方式。

【讨论】:

太好了,这就是我几乎得出的结论——只是错误地在绑定中传递了额外的事件,而当它不存在时(如角度),在这种情况下会自动出现。 是的,这行得通。谢谢。第一个参数中的 null 是什么?我怎样才能传递这个对象进行绑定?【参考方案15】:

一种方法是使用外部函数

elem.addEventListener('click', (function(numCopy) 
  return function() 
    alert(numCopy)
  ;
)(num));

这种将匿名函数包装在括号中并立即调用它的方法称为IIFE(立即调用函数表达式)

您可以在http://codepen.io/froucher/pen/BoWwgz 中查看带有两个参数的示例。

catimg.addEventListener('click', (function(c, i)
  return function() 
    c.meows++;
    i.textContent = c.name + '\'s meows are: ' + c.meows;
  
)(cat, catmeows));

【讨论】:

【参考方案16】:

一种简单的执行方法可能是这样的

    window.addEventListener('click', (e) => functionHandler(e, ...args));

为我工作。

【讨论】:

【参考方案17】:

向 eventListener 的回调函数发送参数需要创建一个隔离函数并将参数传递给该隔离函数。

这是一个不错的小助手功能,您可以使用。基于上面的“hello world”示例。)

还需要一件事是维护对函数的引用,以便我们可以干净地删除侦听器。

// Lambda closure chaos.
//
// Send an anonymous function to the listener, but execute it immediately.
// This will cause the arguments are captured, which is useful when running 
// within loops.
//
// The anonymous function returns a closure, that will be executed when 
// the event triggers. And since the arguments were captured, any vars 
// that were sent in will be unique to the function.

function addListenerWithArgs(elem, evt, func, vars)
    var f = function(ff, vv)
            return (function ()
                ff(vv);
            );
    (func, vars);

    elem.addEventListener(evt, f);

    return f;


// Usage:

function doSomething(withThis)
    console.log("withThis", withThis);


// Capture the function so we can remove it later.
var storeFunc = addListenerWithArgs(someElem, "click", doSomething, "foo");

// To remove the listener, use the normal routine:
someElem.removeEventListener("click", storeFunc);

【讨论】:

这个答案来自 15 年,但这正是我使用 useRef 钩子处理这个问题所需要的。如果您正在使用 ref 挂钩并需要一个侦听器,您可以在卸载组件时对其进行清理,就是这样。 storeFunc 的第 4 个参数应该是您的 ref 变量。将你的监听器移除放在这样的 useEffect 中,你就可以开始了:useEffect(() =&gt; return () =&gt; window.removeEventListener('scroll', storeFunc, false); , [storeFunc])【参考方案18】:

2019年,大量api变化,最佳答案不再有效,没有修复bug。

分享一些工作代码。

受到以上所有答案的启发。

 button_element = document.getElementById('your-button')

 button_element.setAttribute('your-parameter-name',your-parameter-value);

 button_element.addEventListener('click', your_function);


 function your_function(event)
   
      //when click print the parameter value 
      console.log(event.currentTarget.attributes.your-parameter-name.value;)
   

【讨论】:

【参考方案19】:

所有函数内部都有一个特殊变量:arguments。您可以将参数作为匿名参数传递,并通过 arguments 变量访问它们(按顺序)。

例子:

var someVar = some_other_function();
someObj.addEventListener("click", function(someVar)
    some_function(arguments[0]);
, false);

【讨论】:

嗯...投反对票的原因是什么?如果这不是您要查找的内容,请更清楚地解释您的意思(我知道问题已经得到解答)。但是我的代码不是在回答您的要求吗?特殊变量“arguments”使您可以访问函数内的所有参数。【参考方案20】:

当我在循环中使用它来查找元素并向其添加侦听器时,我陷入了困境。如果您在循环中使用它,那么这将完美地工作

for (var i = 0; i < states_array.length; i++) 
     var link = document.getElementById('apply_'+states_array[i].state_id);
     link.my_id = i;
     link.addEventListener('click', function(e)    
        alert(e.target.my_id);        
        some_function(states_array[e.target.my_id].css_url);
     );

【讨论】:

【参考方案21】:

也试试这些(IE8 + Chrome。我不知道 FF):

function addEvent(obj, type, fn) 
    eval('obj.on'+type+'=fn');


function removeEvent(obj, type) 
    eval('obj.on'+type+'=null');


// Use :

function someFunction (someArg) alert(someArg);

var object=document.getElementById('somObject_id') ;
var someArg="Hi there !";
var func=function()someFunction (someArg);

// mouseover is inactive
addEvent (object, 'mouseover', func);
// mouseover is now active
addEvent (object, 'mouseover');
// mouseover is inactive

希望没有错别字:-)

【讨论】:

给出一个完整的答案有多难?我应该在FF上测试这个吗?好吧,我不会打扰...【参考方案22】:

以下答案是正确的,但如果假设您使用 yuicompressor 压缩了 js 文件,则以下代码在 IE8 中不起作用。 (其实美国大部分人还是用IE8)

var someVar; 
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click",
                         function()
                          some_function(someVar);
                         ,
                         false);

所以,我们可以如下解决上述问题,并且在所有浏览器中都可以正常工作

var someVar, eventListnerFunc;
someVar = some_other_function();
eventListnerFunc = some_function(someVar);
someObj.addEventListener("click", eventListnerFunc, false);

希望对在生产环境中压缩js文件的人有用。

祝你好运!!

【讨论】:

【参考方案23】:
    var EV = 
        ev: '',
        fn: '',
        elem: '',
        add: function () 
            this.elem.addEventListener(this.ev, this.fn, false);
        
    ;

    function cons() 
        console.log('some what');
    

    EV.ev = 'click';
    EV.fn = cons;
    EV.elem = document.getElementById('body');
    EV.add();

//If you want to add one more listener for load event then simply add this two lines of code:

    EV.ev = 'load';
    EV.add();

【讨论】:

【参考方案24】:

以下方法对我很有效。修改自here。

function callback(theVar) 
  return function() 
    theVar();
  


function some_other_function() 
  document.body.innerhtml += "made it.";


var someVar = some_other_function;
document.getElementById('button').addEventListener('click', callback(someVar));
<!DOCTYPE html>
<html>
  <body>
    <button type="button" id="button">Click Me!</button>
  </body>
</html>

【讨论】:

【参考方案25】:

由于您的事件监听器是“点击”,您可以:

someObj.setAttribute("onclick", "function(parameter)");

【讨论】:

【参考方案26】:

以下代码对我来说很好用(firefox):

for (var i=0; i<3; i++) 
   element = new ...   // create your element
   element.counter = i;
   element.addEventListener('click', function(e)
        console.log(this.counter);
        ...            // another code with this element
   , false);

输出:

0
1
2

【讨论】:

这到底是什么?【参考方案27】:

你需要:

newElem.addEventListener('click', 
    handleEvent: function (event) 
        clickImg(parameter);
    
);

【讨论】:

【参考方案28】:

可能不是最佳的,但对于那些不精通 js 的人来说已经足够简单了。将调用 addEventListener 的函数放入自己的函数中。这样,传递给它的任何函数值都会保持它们自己的范围,并且您可以根据需要迭代该函数。

示例我解决了文件读取问题,因为我需要捕获和渲染图像和文件名的预览。在使用多文件上传类型时,我花了一些时间来避免异步问题。尽管上传了不同的文件,但我会意外地在所有渲染中看到相同的“名称”。

最初,所有的 readFile() 函数都在 readFiles() 函数中。这导致了异步范围问题。

    function readFiles(input) 
      if (input.files) 
        for(i=0;i<input.files.length;i++) 

          var filename = input.files[i].name;

          if ( /\.(jpe?g|jpg|png|gif|svg|bmp)$/i.test(filename) ) 
            readFile(input.files[i],filename);
          
       
      
     //end readFiles



    function readFile(file,filename) 
            var reader = new FileReader();

            reader.addEventListener("load", function()  alert(filename);, false);

            reader.readAsDataURL(file);

     //end readFile

【讨论】:

【参考方案29】:

只是想补充。如果有人向事件侦听器添加更新复选框的功能,则必须使用event.target 而不是this 来更新复选框。

【讨论】:

【参考方案30】:

我的方法非常简单。这可能对其他人有用,因为它帮助了我。 它是... 当您为多个元素/变量分配了相同的功能并且您想要传递引用时,最简单的解决方案是...

function Name()


this.methodName = "Value"


就是这样。 它对我有用。 如此简单。

【讨论】:

以上是关于如何将参数传递给 addEventListener 监听器函数?的主要内容,如果未能解决你的问题,请参考以下文章

将参数传递给 addEventListener AS3

以简单的方式将参数传递给 AS3 中的事件侦听器......它存在吗?

如何将 POST 参数传递给 Durable Function,然后将此参数传递给 Timer Triggered 函数

如何将参数传递给 Java 线程?

如何将参数传递给进程

如何通过反射将参数传递给方法