删除 JavaScript 类 中的嵌套事件侦听器
Remove nested event listeners in JavaScript classes
我有一个事件监听器,它是由 class 中的函数添加的另一个事件监听器添加的。我希望这个事件侦听器执行一次然后自行删除。
为简化问题,假设我有以下 HTML 代码:
<div class="container">
<div class="redDiv">some html</div>
<div class="blueDiv">some html</div>
</div>
和以下 JavaScript 代码:
class Test {
constructor(_container){
this.container = _container;
}
somefunc(){
// some code here
this.removeEventListener('click',somefunc);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',somefunc);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
我遇到的第一个问题是 somefunc
没有在第二个事件监听器的范围内定义。我找到的唯一解决方案是在 start
函数中创建一个新变量 fnc
并将 somefunc
赋值给它,然后调用 fnc
而不是 somefunc
。
这使得添加事件侦听器和代码 运行 如预期的那样,但是当 somefunc()
被执行时,删除事件侦听器不起作用,因为 somefunc
在这个范围。
我试图通过将代码更改为以下内容来将 somefunc
传递给此范围:
class Test {
constructor(_container){
this.container = _container;
}
somefunc(func){
return function(){
// some code here
this.removeEventListener('click',func);
}
}
start(){
var fnc = this.somefunc;
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',fnc(fnc));
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
现在,代码不会生成任何错误,但事件侦听器未按需要删除。这可能与 JavaScript 分配变量的方式有关,这是我不太了解的主题。但我感兴趣的是如何解决这个问题,并能够在事件侦听器执行后将其删除。
一个解决方案是使用 arrow function 来维护 this
的引用...
class Test {
constructor(_container){
this.container = _container;
}
somefunc(fn){
console.log('clicked blue div')
this.container.querySelector('.blueDiv').removeEventListener('click', fn);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',() => {
console.log('clicked red div')
// Wrap someFunc in an arrow function to have "this" inside somefunc
// reference this class.
const func = () => this.somefunc(func);
container.querySelector('.blueDiv').addEventListener('click', func);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
我有一个事件监听器,它是由 class 中的函数添加的另一个事件监听器添加的。我希望这个事件侦听器执行一次然后自行删除。
为简化问题,假设我有以下 HTML 代码:
<div class="container">
<div class="redDiv">some html</div>
<div class="blueDiv">some html</div>
</div>
和以下 JavaScript 代码:
class Test {
constructor(_container){
this.container = _container;
}
somefunc(){
// some code here
this.removeEventListener('click',somefunc);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',somefunc);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
我遇到的第一个问题是 somefunc
没有在第二个事件监听器的范围内定义。我找到的唯一解决方案是在 start
函数中创建一个新变量 fnc
并将 somefunc
赋值给它,然后调用 fnc
而不是 somefunc
。
这使得添加事件侦听器和代码 运行 如预期的那样,但是当 somefunc()
被执行时,删除事件侦听器不起作用,因为 somefunc
在这个范围。
我试图通过将代码更改为以下内容来将 somefunc
传递给此范围:
class Test {
constructor(_container){
this.container = _container;
}
somefunc(func){
return function(){
// some code here
this.removeEventListener('click',func);
}
}
start(){
var fnc = this.somefunc;
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',function(){
container.querySelector('.blueDiv').addEventListener('click',fnc(fnc));
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();
现在,代码不会生成任何错误,但事件侦听器未按需要删除。这可能与 JavaScript 分配变量的方式有关,这是我不太了解的主题。但我感兴趣的是如何解决这个问题,并能够在事件侦听器执行后将其删除。
一个解决方案是使用 arrow function 来维护 this
的引用...
class Test {
constructor(_container){
this.container = _container;
}
somefunc(fn){
console.log('clicked blue div')
this.container.querySelector('.blueDiv').removeEventListener('click', fn);
}
start(){
var container = this.container;
container.querySelector('.redDiv').addEventListener('click',() => {
console.log('clicked red div')
// Wrap someFunc in an arrow function to have "this" inside somefunc
// reference this class.
const func = () => this.somefunc(func);
container.querySelector('.blueDiv').addEventListener('click', func);
});
}
}
let tester = new Test(document.querySelector('.container'));
tester.start();