Javascript 删除通过绑定添加的事件侦听器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11565471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Removing event listener which was added with bind
提问by takfuruya
In JavaScript, what is the best way to remove a function added as an event listener using bind()?
在 JavaScript 中,使用 bind() 删除作为事件侦听器添加的函数的最佳方法是什么?
Example
例子
(function(){
// constructor
MyClass = function() {
this.myButton = document.getElementById("myButtonID");
this.myButton.addEventListener("click", this.clickListener.bind(this));
};
MyClass.prototype.clickListener = function(event) {
console.log(this); // must be MyClass
};
// public method
MyClass.prototype.disableButton = function() {
this.myButton.removeEventListener("click", ___________);
};
})();
The only way I can think of is to keep track of every listener added with bind.
我能想到的唯一方法是跟踪每个添加了 bind 的监听器。
Above example with this method:
上面这个方法的例子:
(function(){
// constructor
MyClass = function() {
this.myButton = document.getElementById("myButtonID");
this.clickListenerBind = this.clickListener.bind(this);
this.myButton.addEventListener("click", this.clickListenerBind);
};
MyClass.prototype.clickListener = function(event) {
console.log(this); // must be MyClass
};
// public method
MyClass.prototype.disableButton = function() {
this.myButton.removeEventListener("click", this.clickListenerBind);
};
})();
Are there any better ways to do this?
有没有更好的方法来做到这一点?
回答by Ben
Although what @machineghost said was true, that events are added and removed the same way, the missing part of the equation was this:
尽管@machineghost 所说的是正确的,但事件的添加和删除方式相同,但等式中缺失的部分是:
A new function reference is created after
.bind()
is called!
.bind()
调用后会创建一个新的函数引用!
See Does bind() change the function reference? | How to set permanently?
So, to add or remove it, assign the reference to a variable:
因此,要添加或删除它,请将引用分配给变量:
var x = this.myListener.bind(this);
Toolbox.addListener(window, 'scroll', x);
Toolbox.removeListener(window, 'scroll', x);
This works as expected for me.
这对我来说按预期工作。
回答by Raichman Sergey
For those who have this problem while registering/removing listener of React component to/from Flux store, add the lines below to the constructor of your component:
对于那些在向/从 Flux 存储注册/删除 React 组件的侦听器时遇到此问题的人,请将以下行添加到组件的构造函数中:
class App extends React.Component {
constructor(props){
super(props);
// it's a trick! needed in order to overcome the remove event listener
this.onChange = this.onChange.bind(this);
}
// then as regular...
componentDidMount (){
AppStore.addChangeListener(this.onChange);
}
componentWillUnmount (){
AppStore.removeChangeListener(this.onChange);
}
onChange () {
let state = AppStore.getState();
this.setState(state);
}
render() {
// ...
}
}
回答by machineghost
It doesn't matter whether you use a bound function or not; you remove it the same way as any other event handler. If your issue is that the bound version is its own unique function, you can either keep track of the bound versions, or use the removeEventListener
signature that doesn't take a specific handler (although of course that will remove other event handlers of the same type).
是否使用绑定函数并不重要;您以与任何其他事件处理程序相同的方式删除它。如果您的问题是绑定版本是它自己的唯一函数,您可以跟踪绑定版本,或者使用removeEventListener
不采用特定处理程序的签名(当然,这将删除相同类型的其他事件处理程序)。
(As a side note, addEventListener
doesn't work in all browsers; you really should use a library like jQuery to do your event hook-ups in a cross-browser way for you. Also, jQuery has the concept of namespaced events, which allow you to bind to "click.foo"; when you want to remove the event you can tell jQuery "remove all foo events" without having to know the specific handler or removing other handlers.)
(附带说明,addEventListener
并非在所有浏览器中都有效;您确实应该使用像 jQuery 这样的库以跨浏览器的方式为您进行事件连接。此外,jQuery 具有命名空间事件的概念,它允许您绑定到“click.foo”;当您想删除事件时,您可以告诉 jQuery“删除所有 foo 事件”,而无需知道特定的处理程序或删除其他处理程序。)
回答by Ed Kolosovsky
jQuery solution:
jQuery 解决方案:
let object = new ClassName();
let $elem = $('selector');
$elem.on('click', $.proxy(object.method, object));
$elem.off('click', $.proxy(object.method, object));
回答by Peter
We had this problem with a library we could not change. Office Fabric UI, which meant we could not change the way event handlers were added. The way we solved it was to overwrite the addEventListener
on the EventTarget
prototype.
我们在无法更改的库中遇到了这个问题。Office Fabric UI,这意味着我们无法更改添加事件处理程序的方式。我们解决它的方法是覆盖原型addEventListener
上的EventTarget
。
This will add a new function on objects element.removeAllEventListers("click")
这将在对象上添加一个新函数 element.removeAllEventListers("click")
(original post: Remove Click handler from fabric dialog overlay)
(原帖:从结构对话框覆盖中删除点击处理程序)
<script>
(function () {
"use strict";
var f = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function (type, fn, capture) {
this.f = f;
this._eventHandlers = this._eventHandlers || {};
this._eventHandlers[type] = this._eventHandlers[type] || [];
this._eventHandlers[type].push([fn, capture]);
this.f(type, fn, capture);
}
EventTarget.prototype.removeAllEventListeners = function (type) {
this._eventHandlers = this._eventHandlers || {};
if (type in this._eventHandlers) {
var eventHandlers = this._eventHandlers[type];
for (var i = eventHandlers.length; i--;) {
var handler = eventHandlers[i];
this.removeEventListener(type, handler[0], handler[1]);
}
}
}
EventTarget.prototype.getAllEventListeners = function (type) {
this._eventHandlers = this._eventHandlers || {};
this._eventHandlers[type] = this._eventHandlers[type] || [];
return this._eventHandlers[type];
}
})();
</script>
回答by chiic
can use about ES7:
可以使用关于ES7:
class App extends React.Component {
constructor(props){
super(props);
}
componentDidMount (){
AppStore.addChangeListener(this.onChange);
}
componentWillUnmount (){
AppStore.removeChangeListener(this.onChange);
}
onChange = () => {
let state = AppStore.getState();
this.setState(state);
}
render() {
// ...
}
}
回答by Nazar Vynnytskyi
Here is the solution:
这是解决方案:
var o = {
list: [1, 2, 3, 4],
add: function () {
var b = document.getElementsByTagName('body')[0];
b.addEventListener('click', this._onClick());
},
remove: function () {
var b = document.getElementsByTagName('body')[0];
b.removeEventListener('click', this._onClick());
},
_onClick: function () {
this.clickFn = this.clickFn || this._showLog.bind(this);
return this.clickFn;
},
_showLog: function (e) {
console.log('click', this.list, e);
}
};
// Example to test the solution
o.add();
setTimeout(function () {
console.log('setTimeout');
o.remove();
}, 5000);
回答by Diogo Schneider
If you want to use 'onclick', as suggested above, you could try this:
如果你想使用 'onclick',如上所述,你可以试试这个:
(function(){
var singleton = {};
singleton = new function() {
this.myButton = document.getElementById("myButtonID");
this.myButton.onclick = function() {
singleton.clickListener();
};
}
singleton.clickListener = function() {
console.log(this); // I also know who I am
};
// public function
singleton.disableButton = function() {
this.myButton.onclick = "";
};
})();
I hope it helps.
我希望它有帮助。
回答by Noitidart
It's been awhile but MDN has a super explanation on this. That helped me more than the stuff here.
已经有一段时间了,但 MDN 对此有一个超级解释。这对我的帮助不仅仅是这里的东西。
MDN :: EventTarget.addEventListener - The value of "this" within the handler
MDN :: EventTarget.addEventListener - 处理程序中“this”的值
It gives a great alternative to the handleEvent function.
它为 handleEvent 函数提供了一个很好的替代方案。
This is an example with and without bind:
这是一个有和没有绑定的例子:
var Something = function(element) {
this.name = 'Something Good';
this.onclick1 = function(event) {
console.log(this.name); // undefined, as this is the element
};
this.onclick2 = function(event) {
console.log(this.name); // 'Something Good', as this is the binded Something object
};
element.addEventListener('click', this.onclick1, false);
element.addEventListener('click', this.onclick2.bind(this), false); // Trick
}
A problem in the example above is that you cannot remove the listener with bind. Another solution is using a special function called handleEvent to catch any events:
上面示例中的一个问题是您无法使用绑定删除侦听器。另一种解决方案是使用称为 handleEvent 的特殊函数来捕获任何事件: