[英]Passing 'this' and argument to addEventListener function without using bind
當addon禁用時,bootstrapped插件中的removeEventListener不能正常工作 ,我正在探索其他可能性。
除了使用bind()
和緩存綁定函數之外,有沒有辦法使用'this'並傳遞參數?
// works fine but can't pass argeement
contextMenu.addEventListener('popupshowing',
this.contextPopupShowing, false);
// passes the argument but 'this' is no longer available
contextMenu.addEventListener('popupshowing',
function(){this.contextPopupShowing(window);}, false);
我一直在使用bind()
的一些事件監聽器,我正在尋找替代方法而不使用bind()
我甚至嘗試使用<menupopup id="contentAreaContextMenu" ...>
的遞歸函數來抓取window
更新: bind()
干擾removeEventListener
因為我們正在討論無重啟的附加組件......許多無重啟的附加組件使用unload
和unloadWindow
輔助函數,以便更容易正確實現shutdown
,並且還有助於addEventListener
這樣的東西,所以請耐心等待一下。
unload
首先, unload
是一個輔助函數,您將另一個函數傳遞給它,它將在shutdown
運行(或者可以手動調用)。 大多數實現與此非常相似:
var unloaders = []; // Keeps track of unloader functions.
function unload(fn) {
if (typeof(fn) != "function") {
throw new Error("unloader is not a function");
}
unloaders.push(fn);
return function() {
try {
fn();
}
catch (ex) {
Cu.reportError("unloader threw " + fn.toSource());
Cu.reportError(ex);
}
unloaders = unloaders.filter(function(c) { return c != fn; });
};
}
然后你會掛斷shutdown
來做正確的事情:
function shutdown() {
...
for (let i = unloaders.length - 1; i >= 0; --i) {
try {
unloaders[i]();
}
catch (ex) {
Cu.reportError("unloader threw on shutdown " + fn.toSource());
Cu.reportError(ex);
}
}
unloaders.length = 0;
}
unload
現在你可以做以下事情:
function startup() {
setupSomething();
unload(removeSomething);
setupSomethingElse();
var manualRemove = unload(removeSomethingElse);
...
if (condition) {
manualRemove();
}
}
unloadWindow
你通常想要創建第二個函數unloadWindow
以便在你的插件關閉或窗口關閉時卸載東西,無論先發生什么。 在窗口關閉時不刪除東西可能非常棘手,並且非常容易創建bootstrap.js
和/或代碼模塊的Zombie隔離專區 (這來自經驗編寫和審閱無重新啟動的附加組件)。
function unloadWindow(window, fn) {
let handler = unload(function() {
window.removeEventListener('unload', handler, false);
try {
fn();
}
catch (ex) {
Cu.reportError("window unloader threw " + fn.toSource());
Cu.reportError(ex);
}
});
window.addEventListener('unload', handler, false);
};
(有些人可能想要“優化”這個,因為只有一個"unload"
處理程序,但通常你只有這樣的unloadWindow
調用它並不重要。)
現在你可以.bind
東西並做任何事情,讓卸載器關閉跟蹤它。 此外,您可以使用此代碼將關閉代碼保留在初始化代碼旁邊,這可能會提高可讀性。
function setupWindow(window, document) {
var bound = this.contextPopupShowing.bind(this);
contextMenu.addEventListener('popupshowing', bound, false);
unloadWindow(window, function() {
contextMenu.removeEventListener('popupshowing', bound, false);
});
// Or stuff like
var element = document.createElement(...);
contextMenu.appendChild(element);
unloadWindow(window, function() {
contextMenu.removeChild(element);
});
// Or just combine the above into a single unloader
unloadWindow(window, function() {
contextMenu.removeEventListener('popupshowing', bound, false);
contextMenu.removeChild(element);
});
}
在支持bind()
之前,您必須在函數外部保存this
的引用。 然后傳入一個可以按你想要的方式轉發調用的函數。
var self = this;
contextMenu.addEventListener('popupshowing', function() {
self.contextPopupShowing.apply(self, arguments);
}, false);
在這種情況下,我們使用apply
於上下文設置為self
,我們保存的版本this
,並把它的任何arguments
通過魔法傳遞給匿名函數arguments
包含的調用時的函數傳遞參數列表中的關鍵字。
您不必為addEventListener
使用bind
。 您可以使用handleEvent
。 在那個主題中,我也把你聯系起來:
MDN :: EventTarget.addEventListener - 處理程序中“this”的值
handleEvent
實際上是firefox代碼庫中javascript代碼的常用方式。
直接從MDN復制:
var Something = function(element) {
this.name = 'Something Good';
this.handleEvent = function(event) {
console.log(this.name); // 'Something Good', as this is the Something object
switch(event.type) {
case 'click':
// some code here...
break;
case 'dblclick':
// some code here...
break;
}
};
// Note that the listeners in this case are this, not this.handleEvent
element.addEventListener('click', this, false);
element.addEventListener('dblclick', this, false);
// You can properly remove the listners
element.removeEventListener('click', this, false);
element.removeEventListener('dblclick', this, false);
}
我主要使用bind
是在執行for
循環時,我在數組中使用arr[i]
創建匿名函數。 如果我不綁定它,那么它總是只占用數組的最后一個元素,我不知道為什么,我討厭它,所以然后我去使用[].forEach.call(arr, function(arrI)
。
http://2ality.com/2013/06/auto-binding.html
var listener = myWidget.handleClick.bind(myWidget);
domElement.addEventListener('click', listener);
...
domElement.removeEventListener(listener);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.