微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

addEventListener 在匿名回调中调用函数会附加额外的事件吗?

如何解决addEventListener 在匿名回调中调用函数会附加额外的事件吗?

在 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 个事件侦听器主容器元素?

解决方法

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
);

无论如何,它偏离了你原来的问题......

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。