在匿名回调中使用函数调用的 addEventListener 会附加额外的事件吗?
addEventListener with function call inside of anonymous callback attaches extra event?
在 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>
我的代码正在做的是,当用户单击按钮时,它将向主容器元素添加五个新元素(不会删除任何以前的元素),并将向其中的所有子元素添加点击事件侦听器主容器元素的(所以前面的元素也会再次添加事件监听器),所以例如(使用匿名回调方式内部的函数调用)如果我点击按钮3次,我应该在页面上获得 15 个元素和前 5 个元素,每个元素将有 3 个事件监听器附加到它和第二个 5 个元素,每个元素应该有 2 个事件监听器附加到它和最近的 5 个元素,每个元素应该只有 1 个事件侦听器附加到它,但是 为什么当我使用“函数作为回调”方式添加事件侦听器时,无论我点击按钮多少次,它只会添加 1 个事件侦听器到主容器元素内的每个子元素?
参见 here, MDN addEventListener。
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
);
总之,这和你原来的问题有偏差...
在 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>
我的代码正在做的是,当用户单击按钮时,它将向主容器元素添加五个新元素(不会删除任何以前的元素),并将向其中的所有子元素添加点击事件侦听器主容器元素的(所以前面的元素也会再次添加事件监听器),所以例如(使用匿名回调方式内部的函数调用)如果我点击按钮3次,我应该在页面上获得 15 个元素和前 5 个元素,每个元素将有 3 个事件监听器附加到它和第二个 5 个元素,每个元素应该有 2 个事件监听器附加到它和最近的 5 个元素,每个元素应该只有 1 个事件侦听器附加到它,但是 为什么当我使用“函数作为回调”方式添加事件侦听器时,无论我点击按钮多少次,它只会添加 1 个事件侦听器到主容器元素内的每个子元素?
参见 here, MDN addEventListener。
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
);
总之,这和你原来的问题有偏差...