Javascript 正在删除与绑定一起添加的事件侦听器

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

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

})();

有更好的方法吗?

不管你是否使用绑定函数;删除它的方式与删除任何其他事件处理程序的方式相同。如果您的问题是绑定版本是它自己的唯一函数,那么您可以跟踪绑定版本,或者使用不接受特定处理程序的
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() {
    // ...
  }

}