为何eventListener失效但eventHandler正常?点击事件重复触发问题
问题分析与解决方案
核心问题
用addEventListener绑定点击事件后无法移除,导致每次点击都触发(甚至多次触发),根源是**bind()每次调用都会返回一个全新的函数引用**——你绑定的是bind后的新函数,但移除时用原函数或重新bind的函数,都和绑定的引用不匹配,所以移除失败。
而onclick能正常失效,是因为它直接赋值单个函数,设为null就会覆盖掉原有绑定。
解决方案
方案1:提前保存绑定后的函数引用
在绑定事件时,把bind后的函数存到卡片元素的自定义属性上,移除时直接用这个引用:
makeCard(imgSrc, cardSize){ // ... 其他创建元素的代码 ... // 保存bind后的函数引用 const boundFlip = this.flipCard.bind(this, card); card.addEventListener("click", boundFlip); // 把函数存在card上,方便后续移除 card._flipHandler = boundFlip; Card.allCards.push(card); return card; } flipCard(card){ console.log("working"); card.classList.add("active"); // 使用保存的引用移除事件 card.removeEventListener("click", card._flipHandler); }
方案2:用箭头函数+保存引用
利用箭头函数的词法作用域保留this,同时保存函数引用用于移除:
makeCard(imgSrc, cardSize){ // ... 其他创建元素的代码 ... const flipHandler = (e) => this.flipCard(e.currentTarget); card.addEventListener("click", flipHandler); card._flipHandler = flipHandler; Card.allCards.push(card); return card; } flipCard(card){ console.log("working"); card.classList.add("active"); card.removeEventListener("click", card._flipHandler); }
方案3:通过事件对象获取目标元素
不需要提前传递card参数,直接在事件处理函数里通过event.currentTarget拿到卡片,同时保存绑定后的函数引用:
makeCard(imgSrc, cardSize){ // ... 其他创建元素的代码 ... const boundFlip = this.flipCard.bind(this); card.addEventListener("click", boundFlip); card._flipHandler = boundFlip; Card.allCards.push(card); return card; } flipCard(event){ const card = event.currentTarget; console.log("working"); card.classList.add("active"); card.removeEventListener("click", card._flipHandler); }
为什么原移除代码无效?
card.removeEventListener("click", this.flipCard):绑定的是bind后的新函数,和原this.flipCard不是同一个引用,无法匹配移除。card.removeEventListener("click", this.flipCard.bind(this, card)):每次bind都会生成新函数,这个新函数和之前绑定的不是同一个,自然移除失败。
内容的提问来源于stack exchange,提问作者nemanja
相关产品推荐
相关产品推荐

