引入函数导致DOMContentLoaded事件触发两次的解决方法
问题分析
你遇到的问题本质是file1.js的代码被执行了两次,导致DOMContentLoaded事件监听器被注册了两次。即使监听器配置了{ once: true },两次注册的回调仍会在DOM加载完成时各自触发一次,从而出现重复打印和重复执行function2的情况。
解决方案
以下几种方法可以解决这个问题,确保function2只执行一次:
方法一:添加执行标记
在file1.js中增加一个模块级标记变量,用来判断初始化逻辑是否已经执行过:
// file1.js let isInitialized = false; export function function1() {} function function2() {} window.addEventListener('DOMContentLoaded', () => { if (isInitialized) return; isInitialized = true; console.log('dom loaded'); function2(); }, { once: true });
这样即使file1.js的代码被执行多次,第一次执行后isInitialized会被设为true,后续的回调会直接跳过。
方法二:确保模块只加载一次
检查你的页面脚本引用方式,避免同时以普通脚本和ES模块两种方式加载file1.js:
- 如果
file2.js是通过<script type="module" src="file2.js"></script>引入的,那么file1.js会被模块系统自动加载,不需要再单独用<script src="file1.js"></script>引入它。 - 移除页面中重复的
file1.js引用,保证模块只被加载执行一次。
方法三:直接判断DOM状态执行初始化
如果DOMContentLoaded事件还未触发,也可以直接在模块加载时判断DOM状态,避免重复监听:
// file1.js export function function1() {} function function2() {} function init() { console.log('dom loaded'); function2(); } // 检查DOM是否已加载完成 if (document.readyState === 'loading') { window.addEventListener('DOMContentLoaded', init, { once: true }); } else { init(); }
这种方式既处理了DOM未加载的情况,也能在DOM已加载时直接执行初始化,避免不必要的监听重复。
另外注意你的file2.js中有语法错误,import语句结尾应该用分号:
// file2.js import { function1 } from "./file1";
内容的提问来源于stack exchange,提问作者maja
相关产品推荐
相关产品推荐

