[英]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
范围内调用的,因此它使用相同的name
和func
伪代码:
listen(name , func){
window.addEventListener(name, func);
return () => window.removeEventListener( name , func );
}
let remove = listen( 'click' , () => alert('BOO!') );
//cleanup:
remove();
运行下面的代码片段以查看它与多个按钮一起使用
一旦你对事件做更多的事情,就可以为你节省一个小时......
需要注意的是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.