带参数的 Javascript 事件处理程序

我想创建一个传递事件和一些参数的 eventHandler。问题是函数没有得到元素。这里有一个例子:

doClick = function(func){
var elem = .. // the element where it is all about
elem.onclick = function(e){
func(e, elem);
}
}
doClick(function(e, element){
// do stuff with element and the event
});

elem必须在匿名函数之外定义。如何在匿名函数中使用传递的元素?有办法吗?

addEventListener呢?我似乎不能通过事件通过 addEventListener在所有我?

更新

我似乎解决了“这个”的问题

doClick = function(func){
var that = this;
this.element.onclick = function(e){
func(e, that);
}
}

其中包含我可以在函数中访问的 this.element

AddEventListener

但我想知道 addEventListener:

function doClick(elem, func){
element.addEventListener('click', func(event, elem), false);
}
248093 次浏览

I don't understand exactly what your code is trying to do, but you can make variables available in any event handler using the advantages of function closures:

function addClickHandler(elem, arg1, arg2) {
elem.addEventListener('click', function(e) {
// in the event handler function here, you can directly refer
// to arg1 and arg2 from the parent function arguments
}, false);
}

根据具体的编码情况,您几乎总是可以让某种闭包保留对变量的访问。

From your comments, if what you're trying to accomplish is this:

element.addEventListener('click', func(event, this.elements[i]))

然后,您可以使用一个自执行函数(IIFE)来实现这一点,该函数在执行闭包并返回实际的事件处理函数时捕获所需的参数:

element.addEventListener('click', (function(passedInElement) {
return function(e) {func(e, passedInElement); };
}) (this.elements[i]), false);

欲了解更多关于 IIFE 如何工作的信息,请参阅以下其他参考资料:

匿名函数中的 Javascript 包装代码

Immediately-Invoked Function Expression (IIFE) In JavaScript - Passing jQuery

JavaScript 自执行匿名函数的好用例是什么?

最后一个版本可能更容易看到它是这样做的:

// return our event handler while capturing an argument in the closure
function handleEvent(passedInElement) {
return function(e) {
func(e, passedInElement);
};
}


element.addEventListener('click', handleEvent(this.elements[i]));

也可以使用 .bind()向回调中添加参数。传递给 .bind()的任何参数都将被添加到回调本身将具有的参数之前。所以,你可以这样做:

elem.addEventListener('click', function(a1, a2, e) {
// inside the event handler, you have access to both your arguments
// and the event object that the event handler passes
}.bind(elem, arg1, arg2));

doThings内部的 this是窗口对象。请改为:

var doThings = function (element) {
var eventHandler = function(ev, func){
if (element[ev] == undefined) {
return;
}


element[ev] = function(e){
func(e, element);
}
};


return {
eventHandler: eventHandler
};
};

您可以尝试使用 bind 方法,我认为这实现了您的要求。如果没有别的,它仍然非常有用。

function doClick(elem, func) {
var diffElem = document.getElementById('some_element'); //could be the same or different element than the element in the doClick argument
diffElem.addEventListener('click', func.bind(diffElem, elem))
}


function clickEvent(elem, evt) {
console.log(this);
console.log(elem);
// 'this' and elem can be the same thing if the first parameter
// of the bind method is the element the event is being attached to from the argument passed to doClick
console.log(evt);
}


var elem = document.getElementById('elem_to_do_stuff_with');
doClick(elem, clickEvent);

考虑到对原始问题的更新,似乎在传递事件处理程序时上下文(“ this”)有问题。 这里解释一下基础知识 Http://www.w3schools.com/js/js_function_invocation.asp

您的示例的简单工作版本可以读取

var doClick = function(event, additionalParameter){
// do stuff with event and this being the triggering event and caller
}


element.addEventListener('click', function(event)
{
var additionalParameter = ...;
doClick.call(this, event, additionalParameter );
}, false);

参见 Javascript call () & application () vs bind () ?

let obj = MyObject();


elem.someEvent( function(){ obj.func(param) } );


//calls the MyObject.func, passing the param.

这是一个老问题,但却是一个常见的问题。因此,让我在这里加上这个问题。

使用 arrow function syntax,您可以以更简洁的方式实现它,因为它是词法绑定的,并且可以链接。

箭头函数表达式是正则函数表达式的一种语法紧凑的替代方法,尽管它没有自己的 this、参数、 super 或 new.target 关键字绑定。

const event_handler = (event, arg) => console.log(event, arg);
el.addEventListener('click', (event) => event_handler(event, 'An argument'));

If you need to clean up the event listener:

// Let's use use good old function sytax
function event_handler(event, arg) {
console.log(event, arg);
}


// Assign the listener callback to a variable
var doClick = (event) => event_handler(event, 'An argument');


el.addEventListener('click', doClick);


// Do some work...


// Then later in the code, clean up
el.removeEventListener('click', doClick);

这里有一句疯狂的俏皮话:

// You can replace console.log with some other callback function
el.addEventListener('click', (event) => ((arg) => console.log(event, arg))('An argument'));

更温顺的版本 : 更适合任何理智的工作。

el.addEventListener('click', (event) => ((arg) => {
console.log(event, arg);
})('An argument'));

简短的回答:

x.addEventListener("click", function(e){myfunction(e, param1, param2)});


...


function myfunction(e, param1, param1) {
...
}

Try,

const handleOnChange = (event, otherParameter) => {
console.log(`${event.target.value}`);
console.log(`${otherParameter}`);
}


<Select onchange= (event) => {
handleOnChange(event, otherParameter);
}>

这是一个老话题,@jfriend 00非常好地解释了闭包函数调用背后的基础知识。

让我们将代码片段更新到 ES6,并使用另一种技术来帮助我们克服这种情况。

首先让我们定义一个函数 handler这个函数将接收两个参数 fncval,其中 fnc是自定义函数,将处理事件通常是名称 on + theEventName在这种情况下 onClickEvent。这里没什么新鲜事。现在让我们在元素 red上定义 onclick侦听器,它将被称为 clickEventHandler,如下所示:

red.onclick = clickEventHandler

我们注意到 clickEventHandler没有任何参数 Teo, how can I send the ABC1 and the index value to the handler?

问得好,首先让我们调用 handler函数来创建定制的 onClickEvent处理程序,如下所示:

handler(onClickEvent, index)

But Teo, onClickEvent also does NOT have parameters, 我们如何发送闭包函数 ABC0,由 ABC3和 ABC4值产生的 event

耐心点,我年轻的学徒。首先哪个函数将处理 event?在我们的场景中将是 onClickEvent,所以让我们定义这个函数来接收 event eindexv:

function onClickEvent(e, v) {
console.log(`${e.currentTarget.className} -> [x: ${e.x}, y: ${e.y}] | val: ${v}`)
}

现在让我们实现处理程序函数。这个函数将返回一个闭包函数定义,它将执行在 fnc中定义的函数,还将合并闭包函数接收到的参数和 val参数,如下所示:

function handler(fnc, val) {
return (...params) => {
const ctx = this
const arg = [...params, val]
fnc.apply(ctx, arg)
}
}

为了调用 fnc,我们使用 apply()。此方法使用给定的上下文 ctxarg作为数组提供的参数调用指定的函数。因此,使用闭包函数上下文 ctx执行 fnc

这是此场景的一个工作代码片段。

const red = document.querySelector('.red')
const blue = document.querySelector('.blue')


function handler(fnc, val) {
return (...params) => {
const ctx = this
const arg = [...params, val]
fnc.apply(ctx, arg)
}
}


function onClickEvent(e, v) {
console.log(`${e.currentTarget.className} -> [x: ${e.x}, y: ${e.y}] | val: ${v}`)
}


const index = 50


// Define the handler function
const clickEventHandler = handler(onClickEvent, index)


// Call the debounced function on every mouse move
red.onclick = clickEventHandler


blue.addEventListener('click', clickEventHandler)
.boxes {
width: 100%;
height: 120px;
display: flex;
flex-flow: row nowrap;
}


.red {
background: red;
}


.blue {
background: blue;
}


.box {
width: 50%;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
<div class='boxes'>
<div class='red box'>Click Me</div>
<div class='blue box'>Not ready</div>
</div>

Now let's 申请 this concept to your scenario:

const red = document.querySelector('.red')
const blue = document.querySelector('.blue')
red.clicked = false


let clickEventHandler


function handler(fnc, val) {
return (...params) => {
const ctx = this
const arg = [...params, val]
fnc.apply(ctx, arg)
}
}


function onRedClickEvent(e) {
if (red.clicked) return


red.clicked = true
red.textContent = 'Clicked'
blue.textContent = 'Ready'
console.log(`${e.currentTarget.className} -> blue is ready`)


// Define the handler function
clickEventHandler = handler(onClickEvent, red)


// Call the debounced function on every mouse move
blue.addEventListener('click', clickEventHandler)
}


function onClickEvent(e, elem) {
red.clicked = false
red.textContent = 'Click Me'
blue.textContent = 'Not Ready'


console.log(`${e.currentTarget.className} -> [x: ${e.x}, y: ${e.y}] | elem: ${elem.className}`)


blue.removeEventListener('click', clickEventHandler)
}






red.onclick = onRedClickEvent
.boxes {
width: 100%;
height: 120px;
display: flex;
flex-flow: row nowrap;
}


.red {
background: red;
}


.blue {
background: blue;
}


.box {
width: 50%;
display: flex;
justify-content: center;
align-items: center;
color: white;
user-select: none;
}
<div class='boxes'>
<div class='red box'>Click Me</div>
<div class='blue box'>Not ready</div>
</div>