JavaScript移除“onclick”事件监听器

4
我尝试了很多方法,但都没有成功。 我在想这是否不可能? 我知道使用'bind'的“正常”方式,但箭头函数更易读,我更喜欢使用它们。
为了更好地理解我的问题,我编写了这段示例代码,尽可能全面地说明了问题。

class MyClass_XY {

    constructor(zID) {
        let ref = document.getElementById(zID);
        this.name = zID;
        this.Info = ref.querySelector('span');
        this._Bt_Plus = ref.querySelector('.plus');
        this._bt_Stop = ref.querySelector('.stop');

        this.Nbre = 0;
        // this.stop    = false; // I don't whant this, because this is a small sample code of something more complex

        this._Bt_Plus.onclick = e => this._f_Bt_Plus_click(e);
        this._bt_Stop.onclick = e => this._f_Bt_Stop_click(e);

        /*
        this.fct_Ref = null;
        this._Bt_Plus.addEventListener('click', this.fct_Ref = this._f_Bt_Plus_click.bind(this) , false );
        */
    }

    _f_Bt_Plus_click(e) {
        e.stopPropagation();
        console.log(e.target.innerText);
        this.Nbre++,
            this.Info.innerText = this.Nbre.toString();
    }

    _f_Bt_Stop_click(e) {
        e.stopPropagation();

        // this._Bt_Plus.removeEventListener('click', this.fct_Ref  , false ); // is OK, how to deal the other ?

        this._Bt_Plus.removeEventListener("click", this._f_Bt_Plus_click, true); // didn't work :/  

        console.log(this.name, '_Bt_Plus remove onclick ');
    }
}

var
Ananas = new MyClass_XY('Pineapple'), // I am a frog
Bananes = new MyClass_XY('Bananas');
<p id='Pineapple'> pineapple <span>0</span>
    <button class="plus">+1 pineapple</button>
    <button class="stop">stop</button>
</p>

<p id='Bananas'> Bananas <span>0</span>
    <button class="plus">+1 Bananas</button>
    <button class="stop">stop</button>
</p>

2个回答

18
因为您没有使用addEventListener添加监听器,所以removeEventListener不起作用 - 要删除通过赋值给onclick附加的监听器,只需再次将null分配给onclick属性即可:
this._Bt_Plus.onclick = null;

class MyClass_XY {

  constructor(zID) {
    let ref = document.getElementById(zID);
    this.name = zID;
    this.Info = ref.querySelector('span');
    this._Bt_Plus = ref.querySelector('.plus');
    this._bt_Stop = ref.querySelector('.stop');

    this.Nbre = 0;
    // this.stop    = false; // I don't whant this, because this is a small sample code of something more complex

    this._Bt_Plus.onclick = e => this._f_Bt_Plus_click(e);
    this._bt_Stop.onclick = e => this._f_Bt_Stop_click(e);

    /*
    this.fct_Ref = null;
    this._Bt_Plus.addEventListener('click', this.fct_Ref = this._f_Bt_Plus_click.bind(this) , false );
    */
  }

  _f_Bt_Plus_click(e) {
    e.stopPropagation();
    console.log(e.target.innerText);
    this.Nbre++,
      this.Info.innerText = this.Nbre.toString();
  }

  _f_Bt_Stop_click(e) {
    e.stopPropagation();

    // this._Bt_Plus.removeEventListener('click', this.fct_Ref  , false ); // is OK, how to deal the other ?

    this._Bt_Plus.onclick = null;

    console.log(this.name, '_Bt_Plus remove onclick ');
  }
}

var
  Ananas = new MyClass_XY('Pineapple'), // I am a frog
  Bananes = new MyClass_XY('Bananas');
<p id='Pineapple'> pineapple <span>0</span>
  <button class="plus">+1 pineapple</button>
  <button class="stop">stop</button>
</p>

<p id='Bananas'> Bananas <span>0</span>
  <button class="plus">+1 Bananas</button>
  <button class="stop">stop</button>
</p>

如果您使用了addEventListener,那么稍后要使用removeEventListener,您必须引用最初传递给addEventListener的相同函数,例如:

this.plusHandler = e => this._f_Bt_Plus_click(e);
this._Bt_Plus.addEventListener('click', this.plusHandler);

然后

this._Bt_Plus.removeEventListener("click", this.plusHandler);

class MyClass_XY {

    constructor(zID) {
        let ref = document.getElementById(zID);
        this.name = zID;
        this.Info = ref.querySelector('span');
        this._Bt_Plus = ref.querySelector('.plus');
        this._bt_Stop = ref.querySelector('.stop');

        this.Nbre = 0;
        
        this.plusHandler = e => this._f_Bt_Plus_click(e);
        this._Bt_Plus.addEventListener('click', this.plusHandler);
        
        this._bt_Stop.onclick = e => this._f_Bt_Stop_click(e);

        /*
        this.fct_Ref = null;
        this._Bt_Plus.addEventListener('click', this.fct_Ref = this._f_Bt_Plus_click.bind(this) , false );
        */
    }

    _f_Bt_Plus_click(e) {
        e.stopPropagation();
        console.log(e.target.innerText);
        this.Nbre++,
            this.Info.innerText = this.Nbre.toString();
    }

    _f_Bt_Stop_click(e) {
        e.stopPropagation();

        // this._Bt_Plus.removeEventListener('click', this.fct_Ref  , false ); // is OK, how to deal the other ?

        this._Bt_Plus.removeEventListener("click", this.plusHandler);

        console.log(this.name, '_Bt_Plus remove onclick ');
    }
}

var
Ananas = new MyClass_XY('Pineapple'), // I am a frog
Bananes = new MyClass_XY('Bananas');
<p id='Pineapple'> pineapple <span>0</span>
    <button class="plus">+1 pineapple</button>
    <button class="stop">stop</button>
</p>

<p id='Bananas'> Bananas <span>0</span>
    <button class="plus">+1 Bananas</button>
    <button class="stop">stop</button>
</p>


第一种解决方案最简洁,而且如果需要的话还可以重新分配相同的函数(我已经测试过了)。谢谢。 - Mister Jojo
onclick 的问题在于一次只能附加一个监听器,而 addEventListener 大多数情况下要好得多。 - CertainPerformance
你想说的是,如果我有一百个可点击的框,只需更改颜色,那么使用第二种方法会更好,因为它避免了在内存中复制这一百个函数? - Mister Jojo
无论您使用什么方法,该函数都将在内存中 - 毕竟它作为侦听器附加。如果您不想有100个单独的函数(无论您是使用.onclick还是addEventListener),则可以改用事件委派 - 向zID的容器添加单个单击侦听器,从单击元素找到外部ref,然后使用Map来获取该ref的实例化MyClass_XY - CertainPerformance
天啊!我想我得挖掘这个想法。我原本认为在JavaScript中进行事件委托是不可能的,但我刚刚做了一些简要的研究才发现……这将迫使我修改我的代码的某些部分 :/ - Mister Jojo

0
你可以在JS中为元素添加一个类,然后在CSS中将pointer-events属性设置为none。JavaScript。
yourElement.classList.add("no-events");

CSS

.no-events{
   pointer-events: none;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接