触发后无法分离javascript事件

时间:2017-03-15 21:16:53

标签: javascript

我使用此结构创建一次性点击事件:

function structure() {
    this.elements = document.getElementsByClassName('className');
    this.numElements = this.elements.length;

    for(var i = 0; i < this.numElements; i++) {
        this.elements[i].addEventListener('click', this.elementClicked.bind(this));
    }
}

这些事件的处理程序实现如下:

structure.prototype.elementClicked = function(e) {

    // ... processing event

    for(var i = 0; i < this.numElements; i++) {
        this.elements[i].removeEventListener('click', arguments.callee);
    }
};

如果点击了任何已注册的元素,那么想法是触发处理程序一次,然后从每个元素中取消注册事件

不幸的是,每次点击其中一个已注册的项目时,处理程序仍会被解雇

我知道匿名函数不能用于引用同一个对象,但是指定arguments.callee或引用函数的整个名称仍然没有帮助原因

2 个答案:

答案 0 :(得分:1)

每次打电话......

<div class="wrapper">
  <div class="flex-container">
    <div class="box one"></div>
    <div class="box two"></div>
  </div>
</div>

... this.elements[i].addEventListener('click', this.elementClicked.bind(this)); 创建方法的另一个实例。它使用bind,true,但在其他方面是完全不同的功能。这就是为什么你不会使用this.elementClicked上调用的remoteEventListener删除它。

解决方法是什么?一个可能的选项 - 将this.elementClicked作为{ once: true } param传递 - 已在评论中给出,但IE和Edge不支持它(很可能不会被您在最近的Safari中支持未来)。这是另一种方法:

addEventListener

现在为function Structure() { this.elements = document.getElementsByClassName('className'); this.numElements = this.elements.length; // reassign a bound method onto instance: this.elementClicked = this.elementClicked.bind(this); for(var i = 0; i < this.numElements; i++) { this.elements[i].addEventListener('click', this.elementClicked); } } Structure.prototype.elementClicked = function(e) { // ... processing event for(var i = 0; i < this.numElements; i++) { this.elements[i].removeEventListener('click', this.elementClicked); } }; 对象的每个实例创建一个绑定的elementClicked方法,并将其上下文永久设置。

答案 1 :(得分:1)

另一种方法是让您的对象实现 EventListener 接口。您可以通过向构造函数的handleEvent添加.prototype方法,然后传递对象本身来代替事件处理程序来完成此操作。

function Structure() {
    this.elements = document.getElementsByClassName('className');
    this.numElements = this.elements.length;

    for(var i = 0; i < this.numElements; i++) { // v-- pass the object
        this.elements[i].addEventListener('click', this);
    }
}

// Implement the interface; gets invoked when an event occurs
Structure.prototype.handleEvent = function(e) {
  // Used a switch statement in anticipation of other event types
  switch (e.type) {
  case "click":
    this.elementClicked(e);
    break;
  }
};

Structure.prototype.elementClicked = function(e) {
    // ... processing event

    for(var i = 0; i < this.numElements; i++) { //    v-- pass the object
        this.elements[i].removeEventListener('click', this);
    }
};

现在不再需要使用.bind()了。相反,thishandleEvent的值将是绑定对象。您仍然可以通过e.currentTarget获取处理程序绑定到的元素。