繁体   English   中英

移除使用 bind(this) 添加的事件监听器

[英]Remove event listener that has been added using bind(this)

如何在下面的constructor删除绑定到window的单击侦听器? 我需要它来监听window ,我需要访问它里面的按钮实例。

 class MyEl extends HTMLButtonElement { constructor() { super(); this.clickCount = 0; window.addEventListener('click', this.clickHandler.bind(this)); } clickHandler(e) { if (e.target === this) { this.textContent = `clicked ${++this.clickCount} times`; window.removeEventListener('click', this.clickHandler); } } disconnectedCallback() { window.removeEventListener('click', this.clickHandler); } } customElements.define('my-el', MyEl, { extends: 'button' });
 <button is="my-el" type="button">Click me</button>

您当前的实现是不可能的 - .bind每次调用都会创建一个新的单独函数,如果传递的函数与传递给addEventListener函数相同( === ),您只能调用removeEventListener来删除侦听removeEventListener (就像.includes表示数组,或.has表示集合):

 const fn = () => 'foo'; console.log(fn.bind(window) === fn.bind(window));

作为一种解决方法,您可以将绑定函数分配给实例的属性:

 class MyEl extends HTMLButtonElement { constructor() { super(); this.clickCount = 0; this.boundListener = this.clickHandler.bind(this); window.addEventListener('click', this.boundListener); } clickHandler(e) { this.textContent = `clicked ${++this.clickCount} times`; window.removeEventListener('click', this.boundListener); } } customElements.define('my-el', MyEl, { extends: 'button' });
 <button is="my-el" type="button">Click me</button>

像这样为 clickHandler 创建一个包装函数。

 class MyEl extends HTMLButtonElement { constructor() { super(); this.clickCount = 0; this.wrapper = e => this.clickHandler.apply(this, e); window.addEventListener('click', this.wrapper); } clickHandler(e) { this.textContent = `clicked ${++this.clickCount} times`; window.removeEventListener('click', this.wrapper); } } customElements.define('my-el', MyEl, { extends: 'button' });
 <button is="my-el" type="button">Click me</button>

另一种模式是,让您的监听器在构造函数

要删除事件侦听器(无论哪种模式),您都可以在创建事件侦听器时添加“删除”功能

由于 remove函数是在listen范围内调用的,因此它使用相同的namefunc

伪代码:

  listen(name , func){
    window.addEventListener(name, func);
    return () => window.removeEventListener( name , func );
  }

  let remove = listen( 'click' , () => alert('BOO!') );

  //cleanup:
  remove();

运行下面的代码片段以查看它与多个按钮一起使用

事件冒泡 UP & shadowDOM

一旦你对事件做更多的事情,就可以为你节省一个小时......

需要注意的是WebComponents(shadowDOM CustomElements)需要CustomEvents与composed:true财产,如果你想让他们泡过去的shadowDOM边界

    new CustomEvent("check", {
      bubbles: true,
      //cancelable: false,
      composed: true       // required to break out of shadowDOM
    });

删除添加的事件侦听器

注意:这个例子不能在 Safari 上运行,因为 Apple 拒绝实现扩展元素: extends HTMLButtonElement

 class MyEl extends HTMLButtonElement { constructor() { let ME = super();// super() retuns this scope; ME makes code easier to read let count = 0;// you do not have to stick everything on the Element ME.mute = ME.listen('click' , event => { //this function is in constructor scope, so has access to ALL its contents if(event.target === ME) //because ALL click events will fire! ME.textContent = `clicked ${ME.id} ${++count} times`; //if you only want to allow N clicks per button you call ME.mute() here }); } listen(name , func){ window.addEventListener( name , func ); console.log('added' , name , this.id ); return () => { // return a Function! console.log( 'removeEventListener' , name , 'from' , this.id); this.style.opacity=.5; window.removeEventListener( name , func ); } } eol(){ // End of Life this.parentNode.removeChild(this); } disconnectedCallback() { console.log('disconnectedCallback'); this.mute(); } } customElements.define('my-el', MyEl, { extends: 'button' });
 button{ width:12em; }
 <button id="One" is="my-el" type="button">Click me</button> <button onclick="One.mute()">Mute</button> <button onclick="One.eol()">Delete</button> <br> <button id="Two" is="my-el" type="button">Click me too</button> <button onclick="Two.disconnectedCallback()">Mute</button> <button onclick="Two.eol()">Delete</button>

笔记:

  • count不能作为this.count使用,但可用于在构造函数范围内定义的所有函数。 所以它是(有点)私有的,只有点击功能可以更新它。

  • onclick=Two.disconnectedCallback()就像函数不删除元素的例子。


另见: https : //pm.dartus.fr/blog/a-complete-guide-on-shadow-dom-and-event-propagation/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM