You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为带参数的函数正确使用removeEventListener?

解决类中带参数事件监听器的移除问题

问题原因

你当前代码移除监听器失败的核心原因:

  • 添加监听器时用了匿名箭头函数(elem) => this.selectElement(elem, i),每次循环都会生成全新的函数实例,和this.selectElement不是同一个引用,removeEventListener找不到对应函数,自然无法移除。
  • 另外,selectElement是类的箭头函数属性,本身已经绑定了this,构造函数里的this.selectElement = this.selectElement.bind(this)属于多余操作,可以直接删除。

解决方案

方案一:用bind绑定参数并保存函数引用

通过bind生成绑定了参数的函数实例,把这个实例存到元素的自定义属性中,移除时直接调用这个实例即可:

export default class Quiz {
    constructor() {
        this.eventHandlers();
    }
    eventHandlers = () => {
        const listItem = document.querySelectorAll('.answer-menu__item');
    
        listItem.forEach((elem, index) => {
            // 用bind绑定this和index参数,生成固定的函数实例
            const clickHandler = this.selectElement.bind(this, index);
            elem.addEventListener('click', clickHandler);
            // 将函数实例存到元素的dataset中,方便后续移除
            elem.dataset.handler = clickHandler;
        });
    }
    selectElement = (index, event) => {
        const target = event.currentTarget;
        // 取出之前存储的函数实例
        const handler = target.dataset.handler;
        // 移除监听器
        target.removeEventListener('click', handler);
        // 清理存储的函数引用
        delete target.dataset.handler;

        // 这里写你的业务逻辑
        console.log(`选中索引为${index}的选项`);
    }
}

注意:bind绑定参数的顺序是先this,再自定义参数,所以事件触发时,第一个参数是绑定的index,第二个是原生事件对象event。

方案二:通过DOM结构获取索引(无需绑定参数)

如果所有.answer-menu__item都有同一个父元素,可以直接通过元素在父节点中的位置获取索引,避免绑定参数带来的函数引用问题:

export default class Quiz {
    constructor() {
        this.eventHandlers();
    }
    eventHandlers = () => {
        const listItem = document.querySelectorAll('.answer-menu__item');
        listItem.forEach(elem => {
            // 直接绑定原函数,无需包裹匿名函数
            elem.addEventListener('click', this.selectElement);
        });
    }
    selectElement = (event) => {
        const target = event.currentTarget;
        const parent = target.parentElement;
        // 将父元素的子节点转为数组,获取当前元素的索引
        const index = Array.from(parent.children).indexOf(target);
        
        // 直接移除监听器,因为用的是同一个函数引用
        target.removeEventListener('click', this.selectElement);

        // 这里写你的业务逻辑
        console.log(`选中索引为${index}的选项`);
    }
}

这种方式代码更简洁,也不需要额外存储函数引用,适合DOM结构固定的场景。

内容的提问来源于stack exchange,提问作者wowblvck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:30:54