移除使用 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
的那个(就像 .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>
另一种 模式是让你的 Listener 在 构造函数中。
要删除事件监听器(无论什么模式),您可以在创建事件监听器时添加 'remove' 函数。
由于在 listen
范围内调用了 remove 函数,它使用相同的 name
和 func
tion
伪代码:
listen(name , func){
window.addEventListener(name, func);
return () => window.removeEventListener( name , func );
}
let remove = listen( 'click' , () => alert('BOO!') );
//cleanup:
remove();
运行 下面的代码片段 可以看到它与多个按钮一起使用
事件冒泡 UP & shadowDOM
在您处理更多事件后为您节省一个小时...
请注意,WebComponents(即 CustomElements with shadowDOM)需要带有 composed:true
属性 的 CustomEvents,如果你想让它们冒泡 up 超过其 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/
如何在下面的 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
的那个(就像 .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>
另一种 模式是让你的 Listener 在 构造函数中。
要删除事件监听器(无论什么模式),您可以在创建事件监听器时添加 'remove' 函数。
由于在 listen
范围内调用了 remove 函数,它使用相同的 name
和 func
tion
伪代码:
listen(name , func){
window.addEventListener(name, func);
return () => window.removeEventListener( name , func );
}
let remove = listen( 'click' , () => alert('BOO!') );
//cleanup:
remove();
运行 下面的代码片段 可以看到它与多个按钮一起使用
事件冒泡 UP & shadowDOM
在您处理更多事件后为您节省一个小时...
请注意,WebComponents(即 CustomElements with shadowDOM)需要带有 composed:true
属性 的 CustomEvents,如果你想让它们冒泡 up 超过其 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/