我正在研究具有两个视图的浅色图像组件。
我可以通过按一个按钮在两个视图之间切换。当我处于“网格视图”时,我已经设置了一种选择图像的方法,当您单击它时,它将被标记为已选择。
当我加载图像并切换到网格视图时,可以选择和取消选择图像而不会出现问题。如果单击返回单一视图,则返回到网格视图 我无法选择任何图像。如果我第三次这样做,则可以再次选择图像。
通过调试,我发现未删除添加到映像的事件侦听器。在研究这个问题时,我尝试了几种不同的方法,但是没有运气解决这个问题。
这是我所拥有的代码,希望再次提供帮助
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和light元素获得新的帮助。
更新: 这就是我目前所拥有的。 这是单击按钮以切换到网格视图
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,在这里我可以选择一个或多个图像。
然后,当单击单一视图按钮时,它将切换回单一视图,并应从网格视图图像中删除事件侦听器。
所以当我切换回网格视图时,我可以再次选择它们
仍在发生什么。 事件侦听器将被添加到第二个及随后的切换到网格视图的图像上,这意味着它已经执行了多次,因此当我单击它时,它将触发两次。
没有发生什么 事件侦听器不会从图像中删除,因此可以在切换回网格视图时再次对其进行正确设置。
答案 0 :(得分:2)
.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
如果您想一次删除 all 侦听器(例如在视图切换期间),请遍历Map:
boundFnsByImage.forEach((boundFn, image) => {
image.removeEventListener('click', boundFn);
});