首页 > 解决方案 > js:移除或禁用之前添加的某个事件的事件监听器

问题描述

密码笔

以下面的例子(与codepen相同)

const div = document.querySelector('div');

function a(){
  console.log('a');
}

function b(){
  console.log('b');
}

div.addEventListener('click', e=>{
  a();
});

div.addEventListener('click', e=>{
  // I don't want all previous added event handlers to work, is there a way to remove it?
  b();
});
div{
  width: 200px;
  height: 200px;
  background: red;
}
<div></div>

预期的输出是b

在我的原始代码中,我有多个事件处理程序,例如click,mousemove等。有没有一种方法可以删除我之前添加的特定事件的所有事件侦听器?

例如,在开始时,click我的按钮触发function A;在中间,我考虑需要进行功能更改,所以function A我想要function B并且仅触发 ,而不是触发function B

我读过了:

但这并没有太大帮助。谢谢你的帮助。


更新

更具体地说,有没有办法阻止以前添加click的新添加函数内部的事件侦听器,例如:


my_button.addEventListener('click', ()=>{
    console.log('a');
});

my_button.addEventListener('click', ()=>{
    // remove all previously added click handlers 
    console.log('b');
});


解决方案

感谢@Kayac,解决了这个问题:

// add a new method to element, oneEventListener, 
// for a speficified event type, only save and execute last add handler

function elemental(el){
    el.oneEventListener = (event, func) => {
        if(el.lastEventListener == null){
          el.lastEventListener = {};
        }
        if(el.lastEventListener[event] != null){
          el.removeEventListener(event, el.lastEventListener[event]);
        }
        el.addEventListener(event, func);
        el.lastEventListener[event] = func;
    }
    return el;
}

// eventhandler singleton, support querySelector, getElementById, etc, even support querySelectorAll and getElementsByClassName
function proxy(el) {
  if(!(el instanceof NodeList)){
    return elemental(el);
  }else{
    el.forEach(ele=>{
      ele = elemental(ele);
    });
    return el;
  }
}

const div = proxy(document.querySelector('div'));
// const div = document.querySelector('div');

div.oneEventListener('click', e=>{
    console.log('a');
})

div.oneEventListener('click', e=>{
    console.log('b');
})

div.oneEventListener('click', ()=>{
    console.log('c');
})

div.oneEventListener('mouseover', ()=>{
    console.log('aa');
})

div.oneEventListener('mouseover', ()=>{
    console.log('bb');
})

div.oneEventListener('mouseover', ()=>{
    console.log('cc');
})
div{
  width: 200px;
  height: 200px;
  background: red;
}
<div></div>

更新

对于访问者,如果您正在寻找 html 选择器以允许您在事件侦听器上执行单例,则以下代码已针对性能进行了调整。

/* html element selector */

// element: one event maps to one handler
function elemental(el){
  el.oneEventListener = (event, func) => {
    if(el.lastEventListener == null){
      el.lastEventListener = {};
    }
    if(el.lastEventListener[event] != null){
      el.removeEventListener(event, el.lastEventListener[event]);
    }
    el.addEventListener(event, func);
    el.lastEventListener[event] = func;
  }
  return el;
}

// querySelector -> element
function proxy(el){
  return elemental(el);
}

// querySelectorAll -> NodeList
function proxyAll(el){
  el.forEach(ele=>{
    ele = elemental(ele);
  });
  return el;
}

/*
once proxy is implemented, by oneEventListener, 
only one event listener of particular type will exist on that element,
if you call addEventListener, proxy doesn't interfer it.
which the eventlistener added will work normally.
*/

// proxy query selector
const pqs = function(str){
  return proxy(document.querySelector(str));
}

// proxy query selector all
const pqsa = function(str){
  return proxyAll(document.querySelectorAll(str));
}

标签: javascriptaddeventlistenerremoveeventlistener

解决方案


您需要通过引用删除以前的事件监听器: https ://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener

试试这个:

const div = document.querySelector('div');

function a(){
  console.log('a');
}

function b(){
  console.log('b');
}

div.addEventListener('click', a);

// condition for changing event listener
if (true) {
    div.removeEventListener('click', a);
}

div.addEventListener('click', b);

这应该只运行 b


推荐阅读