未删除事件侦听器 - 点亮元素
event listener not being removed - lit element
我正在处理具有两个视图的光照元素图像组件。
- 用户一次只能看到一张图像的单一视图。
- 网格视图,用户可以在其中一次查看所有图像。
我可以按一下按钮在两个视图之间切换。当我在 'grid view' 时,我已经设置了一种方法来 select 一张图片,当你点击它时它会被标记为 selected。
当我加载图像并切换到网格视图时,我可以毫无问题地 select 和 deselect 图像。如果我单击回到单一视图然后 return 到网格视图
我不能 select 任何图像。如果我第三次这样做,我可以再次 select 图片。
通过调试我发现添加到图像的事件侦听器没有被删除。通过对这个问题的研究,我尝试了几种不同的方法,但没有解决这个问题。
这是我的代码,希望有第二眼帮忙
case 'grid':
this.changeViewState(buttonName);
imageItems.forEach((image) => {
image.addEventListener('click', this.selectImage.bind(this,image), false);
});
hiImage.viewMode = 'grid';
break;
selectImage(image){
let hiImage = this._getImageSection().querySelector("hi-images");
hiImage.dispatchEvent(new CustomEvent('selected-images', {
detail: { image: image }
}));
image.removeEventListener('click', this.selectImage.bind(this,image));
}
在此先感谢您的帮助,我可以在 javascript 和 lit element 上获得新的帮助。
更新:
这就是我目前拥有的。
这是单击切换到网格视图的按钮
case 'grid':
this.changeViewState(buttonName);
imageItems.forEach((image) => {
const boundFn = this.selectImage.bind(this, image);
this.boundFnsByImage.set(image, boundFn);
image.addEventListener('click', boundFn);
});
hiImage.viewMode = 'grid';
break;
这是我的按钮点击切换到单一视图这是应该删除事件侦听器的地方。
case 'single':
console.log('gridswitch button was clicked');
this.boundFnsByImage.forEach((boundFn, image) => {
image.removeEventListener('click', boundFn);
});
this.changeViewState(buttonName);
hiImage.viewMode = 'single';
hiImage.dispatchEvent(new CustomEvent('set-nav-icons'));
break;
推送事件调度的SelectImage函数
selectImage(image) {
let hiImage = this._getImageSection().querySelector("hi-images");
hiImage.dispatchEvent(new CustomEvent('selected-images', {
detail: { image: image }
}));
console.log('click selected image');
}
以及这部分组件的属性和构造函数
static get properties() {
return {
name: { type: String }, // ID of the button
tooltip: { type: String },// sets a tooltip for the button
icon: { type: String }, // sets the icon of the button
for: { type: String }, // binds label to input control when it is used
confirmationType: { type: Boolean },
boundFnsByImage: { type: WeakMap }
}
}
constructor() {
super();
this.confirmationType = false;
this.boundFnsByImage = new WeakMap();
}
我想做什么
因此,当单击 gridswitch 按钮时,它会从单一视图变为 gridview- 我可以在其中 select 一张或多张图片。
然后,当单击单一视图按钮时,它会切换回单一视图,并且应该从网格视图图像中删除事件侦听器。
所以当我切换回网格视图时,我可以再次 select 它们
还在发生什么。
事件侦听器被添加到第二次和后续切换到网格视图时的图像中,这意味着它不止一次这样做,所以当我点击它时它会触发两次。
没有发生什么
事件侦听器不会从图像中删除,因此在切换回网格视图时可以再次正确设置它们。
当您 .bind
一个函数时,您创建了一个 全新的 函数,它不是 ===
之前可能存在的任何函数(即使使用相同的过程创建)。所以
this.selectImage.bind(this,image) === this.selectImage.bind(this,image)
将计算为 false
- ===
引用 不同函数 对象每一侧的表达式。
因为 selectImage
看起来要删除侦听器,所以一种选择是改用 { once: true }
以确保侦听器只运行一次:
imageItems.forEach((image) => {
image.addEventListener('click', this.selectImage.bind(this, image), { once: true });
});
另一种方法是将绑定函数存储在某处,以便稍后可以调用 removeEventListener
,例如
const boundFnsByImage = new Map();
// ...
imageItems.forEach((image) => {
const boundFn = this.selectImage.bind(this, image);
boundFnsByImage.set(image, boundFn);
image.addEventListener('click', boundFn);
});
然后用
检索它
selectImage(image){
let hiImage = this._getImageSection().querySelector("hi-images");
hiImage.dispatchEvent(new CustomEvent('selected-images', {
detail: { image: image }
}));
const boundFn = boundFnsByImage.get(image); // <----------------------
// if you want to remove the listener when clicked:
image.removeEventListener('click', boundFn);
}
另请注意,无需将第三个 useCapture
参数传递给 addEventListener
除非您 想要 使用捕获 - 它会默认为 false
无论如何。
如果你想一次性移除所有个侦听器(比如在视图切换期间),那么遍历地图:
boundFnsByImage.forEach((boundFn, image) => {
image.removeEventListener('click', boundFn);
});
我正在处理具有两个视图的光照元素图像组件。
- 用户一次只能看到一张图像的单一视图。
- 网格视图,用户可以在其中一次查看所有图像。
我可以按一下按钮在两个视图之间切换。当我在 'grid view' 时,我已经设置了一种方法来 select 一张图片,当你点击它时它会被标记为 selected。
当我加载图像并切换到网格视图时,我可以毫无问题地 select 和 deselect 图像。如果我单击回到单一视图然后 return 到网格视图 我不能 select 任何图像。如果我第三次这样做,我可以再次 select 图片。
通过调试我发现添加到图像的事件侦听器没有被删除。通过对这个问题的研究,我尝试了几种不同的方法,但没有解决这个问题。
这是我的代码,希望有第二眼帮忙
case 'grid':
this.changeViewState(buttonName);
imageItems.forEach((image) => {
image.addEventListener('click', this.selectImage.bind(this,image), false);
});
hiImage.viewMode = 'grid';
break;
selectImage(image){
let hiImage = this._getImageSection().querySelector("hi-images");
hiImage.dispatchEvent(new CustomEvent('selected-images', {
detail: { image: image }
}));
image.removeEventListener('click', this.selectImage.bind(this,image));
}
在此先感谢您的帮助,我可以在 javascript 和 lit element 上获得新的帮助。
更新: 这就是我目前拥有的。 这是单击切换到网格视图的按钮
case 'grid':
this.changeViewState(buttonName);
imageItems.forEach((image) => {
const boundFn = this.selectImage.bind(this, image);
this.boundFnsByImage.set(image, boundFn);
image.addEventListener('click', boundFn);
});
hiImage.viewMode = 'grid';
break;
这是我的按钮点击切换到单一视图这是应该删除事件侦听器的地方。
case 'single':
console.log('gridswitch button was clicked');
this.boundFnsByImage.forEach((boundFn, image) => {
image.removeEventListener('click', boundFn);
});
this.changeViewState(buttonName);
hiImage.viewMode = 'single';
hiImage.dispatchEvent(new CustomEvent('set-nav-icons'));
break;
推送事件调度的SelectImage函数
selectImage(image) {
let hiImage = this._getImageSection().querySelector("hi-images");
hiImage.dispatchEvent(new CustomEvent('selected-images', {
detail: { image: image }
}));
console.log('click selected image');
}
以及这部分组件的属性和构造函数
static get properties() {
return {
name: { type: String }, // ID of the button
tooltip: { type: String },// sets a tooltip for the button
icon: { type: String }, // sets the icon of the button
for: { type: String }, // binds label to input control when it is used
confirmationType: { type: Boolean },
boundFnsByImage: { type: WeakMap }
}
}
constructor() {
super();
this.confirmationType = false;
this.boundFnsByImage = new WeakMap();
}
我想做什么 因此,当单击 gridswitch 按钮时,它会从单一视图变为 gridview- 我可以在其中 select 一张或多张图片。
然后,当单击单一视图按钮时,它会切换回单一视图,并且应该从网格视图图像中删除事件侦听器。
所以当我切换回网格视图时,我可以再次 select 它们
还在发生什么。 事件侦听器被添加到第二次和后续切换到网格视图时的图像中,这意味着它不止一次这样做,所以当我点击它时它会触发两次。
没有发生什么 事件侦听器不会从图像中删除,因此在切换回网格视图时可以再次正确设置它们。
当您 .bind
一个函数时,您创建了一个 全新的 函数,它不是 ===
之前可能存在的任何函数(即使使用相同的过程创建)。所以
this.selectImage.bind(this,image) === this.selectImage.bind(this,image)
将计算为 false
- ===
引用 不同函数 对象每一侧的表达式。
因为 selectImage
看起来要删除侦听器,所以一种选择是改用 { once: true }
以确保侦听器只运行一次:
imageItems.forEach((image) => {
image.addEventListener('click', this.selectImage.bind(this, image), { once: true });
});
另一种方法是将绑定函数存储在某处,以便稍后可以调用 removeEventListener
,例如
const boundFnsByImage = new Map();
// ...
imageItems.forEach((image) => {
const boundFn = this.selectImage.bind(this, image);
boundFnsByImage.set(image, boundFn);
image.addEventListener('click', boundFn);
});
然后用
检索它selectImage(image){
let hiImage = this._getImageSection().querySelector("hi-images");
hiImage.dispatchEvent(new CustomEvent('selected-images', {
detail: { image: image }
}));
const boundFn = boundFnsByImage.get(image); // <----------------------
// if you want to remove the listener when clicked:
image.removeEventListener('click', boundFn);
}
另请注意,无需将第三个 useCapture
参数传递给 addEventListener
除非您 想要 使用捕获 - 它会默认为 false
无论如何。
如果你想一次性移除所有个侦听器(比如在视图切换期间),那么遍历地图:
boundFnsByImage.forEach((boundFn, image) => {
image.removeEventListener('click', boundFn);
});