如何解决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));
}
解决方法
您需要通过引用删除以前的事件侦听器: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
尝试一下:
class CancellablePromise extends Promise {
constructor(executor) {
let cancel = null
super((resolve,reject) => {
cancel = reject
executor(resolve,reject)
})
this.cancel = cancel
}
}
const p = new CancellablePromise((resolve) => setTimeout(resolve,1000))
.then(() => console.log('success'))
.catch((err) => console.log('rejected',err))
p.cancel() // Uncaught exception
这只能运行b
,您尝试过吗?
它会删除addEventListener()方法附带的“ click”事件:
示例
Symbol.species
,
尝试一下
function a() {
console.log("a");
}
function b() {
console.log("b");
}
function proxy(el) {
const map = {};
return {
addEventListener: (event,func) => {
!map[event] && el.addEventListener(event,() => map[event]());
map[event] = func;
}
};
}
const div = proxy(document.querySelector("div"));
div.addEventListener("click",a);
div.addEventListener("click",b);
,
恐怕您必须自己使用addEventListener
来跟踪要附加到元素上的事件。没有内置方法可以查询这些内容。
要使用removeEventListener
成功删除事件,该事件必须与对addEventListener的调用具有相同的签名。
这是通过使用命名函数而不是匿名函数来完成的。
例如:
var myButton = document.getElementById("myButton");
var myButton2 = document.getElementById("myButton2");
function a() {
console.log("function a");
}
function b() {
console.log("function b");
}
function changeFunction() {
myButton.removeEventListener('click',a);
myButton.addEventListener('click',b);
}
myButton.addEventListener('click',a);
myButton2.addEventListener('click',changeFunction);
<button id="myButton">
click me
</button>
<button id="myButton2">
attach new listener
</button>
,
没有做到这一点的直接方法。
但是,如果您控制所有侦听器的添加和删除,则可以收集侦听器并删除所有侦听器,如下所示:
const elements = new WeakMap
function customAddEventListener(elem,event,fn){
elem.addEventListener(event,fn)
if(!elements.has(elem)) elements.set(elem,Object.create(null))
const events = elements.get(elem)
if(!(event in events)) events[event] = new Set
const fns = events[event]
fns.add(fn)
}
function customRemoveEventListener(elem,fn){
elem.removeEventListener(event,fn)
if(!elements.has(elem)) return
const events = elements.get(elem)
if(!event in events) return
const fns = events[event]
fns.delete(fn)
if(!fns.size) delete events[event]
if(!Reflect.ownKeys(events).length) elements.delete(elem)
}
function removeAllEventListeners(elem,event){
if(!elements.has(elem)) return
const events = elements.get(elem)
if(!event in events) return
const fns = events[event]
for(const fn of fns)
elem.removeEventListener(event,fn)
delete events[event]
if(!Reflect.ownKeys(events).length) elements.delete(elem)
}
const div = document.querySelector('#div');
function a(){
console.log('a');
}
function b(){
console.log('b');
}
customAddEventListener(div,'click',e=>{
a();
});
customAddEventListener(div,function fn(e){
b();
removeAllEventListeners(div,'click')
//add this one back
customAddEventListener(div,fn)
});
#div{
width: 200px;
height: 200px;
background: red;
}
<div id="div"></div>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。