问题描述
在 addEventListener 的匿名回调中使用我的函数和在 addEventListener 的回调中使用我的函数有什么区别?
示例代码:
/* function call inside of anonymous callback
=> Attaches extra event
*/
childEl.addEventListener('click',(e)=>{
handler(e);
});
/* function as callback
=> Only attaches one event
*/
childEl.addEventListener('click',handler);
因为我不明白,为什么在 addEventListener 的匿名回调中调用我的函数会将额外的事件附加到我的元素,如果我使用函数作为回调,它只会将一个事件附加到我的元素...
(关于我的问题的更多信息在最后)
js
const mainContainerEl = document.querySelector('.main-container');
const btnEl = document.querySelector('button');
console.log(mainContainerEl);
console.log(btnEl);
const handler = (e) => {
console.log(e.target.textContent);
};
btnEl.addEventListener('click',()=>{
for(let i = 1; i <= 5; i++){
const newSpanEl = document.createElement('span');
newSpanEl.textContent = i;
mainContainerEl.append(newSpanEl);
}
if(mainContainerEl.children){
const mainContainerElChildren = [...mainContainerEl.children];
mainContainerElChildren.forEach((childEl)=>{
/* function call inside of anonymous callback
=> Attaches extra event
*/
childEl.addEventListener('click',(e)=>{
handler(e);
});
/* function as callback
=> Only attaches one event
*/
childEl.addEventListener('click',handler);
});
}
});
html 和 css
span {
display: inline-block;
padding: 10px;
border: 2px solid darkBlue;
}
button {
margin-top: 10px;
}
--------------------------------------------------
<body>
<div class="main-container"></div>
<button>Click to add elements</button>
<script src="./scripts.js"></script>
</body>
我的代码正在做的是,当用户单击按钮时,它会将五个新元素附加到主容器元素(不会删除任何以前的元素),并将单击事件侦听器添加到 main 内的所有子元素-container 元素(所以之前的元素也会再次添加事件监听器),例如 (使用匿名回调方式内部的函数调用) 如果我点击按钮 3 次,我应该得到 15 个元素页面和前 5 个元素,每个元素将有 3 个事件监听器附加到它,第二个 5 个元素,每个元素应该有 2 个事件监听器附加到它和最近的 5 个元素,每个元素应该只有 1 个事件监听器附加到它但是为什么当我使用“函数作为回调”的方式添加事件侦听器时,我单击按钮的次数无关紧要,它只会向其中的每个子项添加 1 个事件侦听器主容器元素?
解决方法
handler === handler
是真的,但是
((e) => {console.log(e.target.textContent);}) === ((e) =>{console.log(e.target.textContent);})
为 false 以便在多次添加匿名函数时不会添加两次或更多次处理程序。
更新:如果你想更新你的事件监听器,删除之前附加的匿名函数,首先你将它保存到你的元素中,
my_element.my_func = (e) => {...};
my_element.addEventListener('click',my_element.my_func);
然后删除该函数并附加另一个新函数;
my_element.removeEventListener('click',my_element.my_func);
my_element.my_func = (e) => {...}; // New definition
my_element.addEventListener('click',my_element.my_func);
当然,有很多方法可以做到这一点,以上只是其中一种。
更新:遵循@JaffaTheCake 的建议;
btnEl.addEventListener('click',(function(){
for(let i = 1; i <= 5; i++){
const newSpanEl = document.createElement('span');
newSpanEl.textContent = i;
mainContainerEl.append(newSpanEl);
}
if(mainContainerEl.children){
const mainContainerElChildren = [...mainContainerEl.children];
mainContainerElChildren.forEach((childEl)=>{
if (this.wm.get(childEl)) {
childEl.removeEventListener('click',this.wm.get(childEl));
}
// Anonymous function of your choice
this.wm.set(childEl,(e)=>{handler(e);});
childEl.addEventListener('click',this.wm.get(childEl));
});
}
}).bind({wm: new WeakMap()}) // bind cannot be used with arrow functions
);
无论如何,它偏离了你原来的问题......