Javascript 正在删除与绑定一起添加的事件侦听器
在JavaScript中,使用bind()删除作为事件侦听器添加的函数的最佳方法是什么 范例Javascript 正在删除与绑定一起添加的事件侦听器,javascript,events,listener,bind,Javascript,Events,Listener,Bind,在JavaScript中,使用bind()删除作为事件侦听器添加的函数的最佳方法是什么 范例 (function(){ // constructor MyClass = function() { this.myButton = document.getElementById("myButtonID"); this.myButton.addEventListener("click", this.clickListener.bind(this));
(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);
};
})();
有更好的方法吗?不管你是否使用绑定函数;删除它的方式与删除任何其他事件处理程序的方式相同。如果您的问题是绑定版本是它自己的唯一函数,那么您可以跟踪绑定版本,或者使用不接受特定处理程序的
removeEventListener
签名(当然,这将删除相同类型的其他事件处理程序)
(作为旁注,
addEventListener
并不适用于所有浏览器;您确实应该使用类似jQuery的库以跨浏览器的方式为您进行事件连接。此外,jQuery还具有命名空间事件的概念,允许您绑定到“click.foo”;当您想要删除事件时,可以告诉jQuery“删除所有foo事件”,而不必知道特定的处理程序或删除其他处理程序。)如果要使用上面建议的“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 = "";
};
})();
我希望这能有所帮助。尽管@MachineHost所说的是真的,事件是以同样的方式添加和删除的,但等式中缺少的部分是: 调用
.bind()
后将创建一个新的函数引用
看
因此,要添加或删除它,请将引用指定给变量:
var x = this.myListener.bind(this);
Toolbox.addListener(window, 'scroll', x);
Toolbox.removeListener(window, 'scroll', x);
这对我来说就像预期的一样。已经有一段时间了,但是MDN对此有一个很好的解释。这比这里的东西对我帮助更大 它为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的特殊函数捕获任何事件:对于那些在将React组件的侦听器注册到Flux store或从Flux store中删除侦听器时遇到此问题的人,请将以下行添加到组件的构造函数中:
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
//这是一个技巧!需要克服移除事件侦听器
this.onChange=this.onChange.bind(this);
}
//然后像往常一样。。。
组件安装(){
AppStore.addChangeListener(this.onChange);
}
组件将卸载(){
AppStore.removeChangeListener(this.onChange);
}
onChange(){
让state=AppStore.getState();
本.设置状态(状态);
}
render(){
// ...
}
}
解决方案如下:
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);
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,这意味着我们无法更改添加事件处理程序的方式。解决此问题的方法是覆盖
EventTarget
原型上的addEventListener
这将在对象元素上添加一个新函数。删除AlleventListers(“单击”)
(原职:)
(功能(){
“严格使用”;
var f=EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener=函数(类型、fn、捕获){
这个。f=f;
this._eventHandlers=this._eventHandlers | |{};
此._eventHandlers[type]=此._eventHandlers[type]| |[];
此._eventHandlers[type].push([fn,capture]);
此.f(类型、fn、捕获);
}
EventTarget.prototype.removeAllEventListeners=函数(类型){
this._eventHandlers=this._eventHandlers | |{};
if(输入此.\u eventHandlers){
var eventHandlers=this.\u eventHandlers[type];
for(var i=eventHandlers.length;i--;){
var handler=eventHandlers[i];
this.removeEventListener(类型,处理程序[0],处理程序[1]);
}
}
}
EventTarget.prototype.getAllEventListeners=函数(类型){
this._eventHandlers=this._eventHandlers | |{};
此._eventHandlers[type]=此._eventHandlers[type]| |[];
返回此项。_eventHandlers[type];
}
})();
可以使用关于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() {
// ...
}
}
除了
this.clickListener=this.clickListener.bind(this);
和this.myButton.addEventListener(“click”,this.clickListener);
这很好。这可能是一个不同的主题,但这让我想知道是否应该为使用“this”的其余方法绑定(this)“关键字,即使它会使方法调用效率低下。对于将要传递到某个位置的所有方法,我总是在构造函数中首先这样做,不管我以后是否要删除它们。但不是所有的方法,只是那些被传递的方法。你所做的是有意义的。但是,例如,如果这是库的一部分,您永远无法知道将传递哪些MyClass的方法(记录为“public”)。仅供参考,下划线库有一个简化绑定方法的bindAll
函数。在对象初始值设定项中,您只需执行\uu.bindAll(this)
即可将对象中的每个方法设置为绑定版本。或者,如果您只想绑定一些方法(我建议您这样做,以防止意外内存泄漏),可以将它们作为参数提供:.bindAll(this,“foo”,“bar”)//this.baz将不被绑定
。我知道IE的问题。我正在开发一个严重依赖canvas的应用程序,因此IE7已经过时了。IE8支持画布,但至少支持画布。IE9+支持加法器
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() {
// ...
}
}