簡體   English   中英

Javascript 帶參數的事件處理器

[英]Javascript event handler with parameters

我想制作一個eventHandler事件和一些參數的事件處理程序。 問題是 function 沒有獲取元素。 這是一個例子:

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必須在匿名 function 之外定義。如何讓傳遞的元素在匿名 function 中使用? 有沒有辦法做到這一點?

addEventListener呢? 我似乎根本無法通過addEventListener傳遞事件,對嗎?

更新

我似乎用“這個”解決了問題

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

其中包含我可以在this.element中訪問的 this.element。

添加事件監聽器

但我想知道addEventListener

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

我不明白你的代碼到底想做什么,但你可以利用 function 閉包的優勢使變量在任何事件處理程序中可用:

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

根據您的具體編碼情況,您幾乎總是可以讓某種閉包為您保留對變量的訪問。

根據您的評論,如果您要完成的是:

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

然后,您可以使用自執行 function (IIFE) 執行此操作,它在閉包執行時捕獲您想要的 arguments 並返回實際事件處理程序 function:

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

有關 IIFE 如何工作的更多信息,請參閱以下其他參考資料:

Javascript 匿名包裝代碼 function

立即調用 Function 表達式 (IIFE) 在 JavaScript - 傳遞 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()將 arguments 添加到回調中。 您傳遞給.bind()的任何 arguments 都將添加到回調本身將具有的 arguments 之前。 所以,你可以這樣做:

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

這是一個古老的問題,但卻是一個普遍的問題。 所以讓我在這里添加這個。

使用箭頭 function 語法,您可以更簡潔地實現它,因為它是詞法綁定的並且可以鏈接。

箭頭 function 表達式是常規 function 表達式的語法緊湊替代方案,盡管它自己沒有綁定到 this、arguments、super 或 new.target 關鍵字。

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

如果您需要清理事件偵聽器:

// 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'));

您可以嘗試使用 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() & apply() vs bind()?

簡短回答:

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

... 

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

嘗試,

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

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

this的內部是doThings object。試試這個:

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

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

    return {
        eventHandler: eventHandler
    };
};

這是一個老話題,@jfriend00 做了非常好的工作,解釋了閉包 function 調用背后的基礎知識。

讓我們將代碼片段更新為 ES6,並使用另一種可能幫助我們克服這種情況的技術。

首先讓我們定義一個 function handler ,此 function 將接收兩個參數fncval ,其中fnc是將處理事件的自定義 function 通常是 names on + theEventName在這種情況下onClickEvent 這里沒有什么新鮮事。 現在讓我們在元素red上定義onclick偵聽器,它將像這樣調用clickEventHandler

red.onclick = clickEventHandler

正如我們注意到clickEventHandler沒有任何參數Teo,我如何將eventindex值發送到處理程序?

好問題,首先讓我們調用handler function 來創建我們的自定義onClickEvent處理程序,如下所示:

handler(onClickEvent, index)

但是 Teo, onClickEvent也沒有參數,我們如何發送閉包 function onClickEventonclick產生的eventindex值?

耐心等待我年輕的學徒。 首先哪個 function 將處理該event 在我們的場景中將是onClickEvent所以讓我們定義這個 function 來接收event eindexv

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

現在讓我們實現我們的處理程序 function。這個 function 將返回一個閉包 function 定義,它將執行在fnc中定義的 function,還將合並閉包 function 接收的參數和val參數,如下所示:

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

我們使用apply()來調用fnc 此方法使用給定的上下文ctx調用指定的 function,並將arg作為數組提供的 arguments。 因此, fnc使用閉包 function 上下文ctx執行。

這是此場景的工作片段。

 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: ${ex}, y: ${ey}] | 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>

現在讓我們這個概念應用到您的場景中:

 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: ${ex}, y: ${ey}] | 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>

let obj = MyObject();

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM