在JavaScript中,删除使用bind()添加为事件侦听器的函数的最佳方法是什么?
例
(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", ___________);
};
})();
我能想到的唯一方法是跟踪添加了bind的每个侦听器。
上面的示例使用此方法:
(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);
};
})();
有没有更好的方法可以做到这一点?
尽管@machineghost所说的是正确的,但事件的添加和删除方式相同,但等式中缺少的部分是:
.bind()
调用后会创建一个新的函数引用!
因此,要添加或删除它,请将引用分配给变量:
var x = this.myListener.bind(this);
Toolbox.addListener(window, 'scroll', x);
Toolbox.removeListener(window, 'scroll', x);
这对我来说是预期的。
对于那些在将React组件的侦听器注册到Flux存储中或从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() {
// ...
}
}
是否使用绑定函数都没有关系。您可以像其他事件处理程序一样删除它。如果您的问题是绑定版本是其自身的唯一功能,则可以跟踪绑定版本,或者使用removeEventListener
不带特定处理程序的签名(尽管当然会删除其他相同类型的事件处理程序) )。
(请注意,addEventListener
并非在所有浏览器中都起作用;您确实应该使用jQuery之类的库为您跨浏览器方式进行事件连接。而且,jQuery具有命名空间事件的概念,您绑定到“ click.foo”;当您想要删除事件时,您可以告诉jQuery“删除所有foo事件”,而不必知道特定的处理程序或删除其他处理程序。)
jQuery解决方案:
let object = new ClassName();
let $elem = $('selector');
$elem.on('click', $.proxy(object.method, object));
$elem.off('click', $.proxy(object.method, object));
我们在无法更改的库中遇到了这个问题。Office Fabric UI,这意味着我们无法更改事件处理程序的添加方式。我们解决它的方法是覆盖addEventListener
的EventTarget
原型。
这将在对象上添加新功能 element.removeAllEventListers("click")
(原始文章:从结构对话框叠加层中删除Click处理程序)
<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>
解决方法如下:
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);
可以使用关于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() {
// ...
}
}
如果您要使用“ 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 = "";
};
})();
希望对您有所帮助。
已经有一段时间了,但是MDN对此有一个很好的解释。那对我的帮助远胜于这里的东西。
MDN :: EventTarget.addEventListener-处理程序中“ this”的值
它为handleEvent函数提供了很好的选择。
这是有和没有绑定的示例:
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
}
上面的示例中的问题是您无法使用bind删除侦听器。另一种解决方案是使用一个名为handleEvent的特殊函数来捕获所有事件:
文章标签:bind , events , javascript , listener
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!