JavaScript事件监听器未按预期触发:部分通知关闭按钮事件不生效
问题根因分析
- 核心原因:
innerHTML +=操作会销毁原有DOM节点
你每次调用siloElement.innerHTML += notification_template.trim()时,浏览器会先将siloElement下所有现存的DOM节点全部删除,把现有innerHTML序列化为字符串,拼接上新的模板字符串后,再整体重新解析为DOM节点。之前给前序通知关闭按钮绑定的click事件监听器是绑定在被销毁的旧节点上的,新渲染出来的前序通知节点没有绑定任何事件,只有最后一次新增后绑定的最后一条通知的事件是有效的。 - 潜在风险:绝对定位元素的层级覆盖
所有.notification都是绝对定位,且未显式设置z-index,默认后创建的DOM节点层级高于先创建的,若节点存在重叠区域,上层节点会拦截下层节点的点击事件。
修复方案
不要用innerHTML +=拼接内容,改用insertAdjacentHTML来追加新节点,该API只会在容器末尾插入新的DOM节点,不会修改/销毁已存在的节点,之前绑定的事件监听器就会全部保留:
把原代码中的
siloElement.innerHTML += notification_template.trim();
替换为:
siloElement.insertAdjacentHTML('beforeend', notification_template.trim());
额外优化建议
可以用事件委托替代逐个绑定事件,直接给siloElement绑定一次click事件即可,后续新增通知不需要重复绑定事件,性能更优:
// 这段代码仅需在页面初始化时执行一次,不需要放在show函数内 document.querySelector('#notification-silo').addEventListener('click', e => { if (e.target.matches('.close-wrapper button')) { console.log('click is fired'); // 可直接补充关闭通知逻辑,示例如下 e.target.closest('.notification').remove(); } });
内容的提问来源于stack exchange,提问作者P.Petkov
相关产品推荐
相关产品推荐

