根据屏幕宽度条件加载外部JS后引用出现undefined如何解决
问题根因
你遇到的报错有两个核心诱因:
- 动态插入的
<script>标签默认是异步加载的,浏览器不会阻塞后续代码执行,不等外部JS下载、解析完成就会直接执行<body>里的初始化代码,此时Swiper构造函数还没挂载到全局,所以报undefined。 - 你在head的script块里用const定义的
viewWidth是块级作用域变量,仅在当前script块内有效,body里的script块直接访问会先抛出变量未定义错误。
解决方案
方案1:绑定onload事件(最简实现)
直接将Swiper初始化逻辑绑定到动态脚本的加载完成事件,不需要拆分逻辑到两个script块:
<head> <script> const viewWidth = window.innerWidth; if (viewWidth >= 480) { console.log('big screen'); const swiperJS = document.createElement('script'); swiperJS.type = "text/javascript"; swiperJS.src = "https://cdnjs.cloudflare.com/ajax/libs/Swiper/7.2.0/swiper-bundle.min.js"; // 脚本加载完成后再执行初始化 swiperJS.onload = function() { const swiper = new Swiper('.swiper'); } document.head.appendChild(swiperJS); } </script> </head> <body> <!-- 无需额外写Swiper初始化逻辑 --> </body>
方案2:Promise封装(适合多段依赖逻辑)
如果必须把初始化逻辑放在<body>中,用Promise封装加载过程,所有依赖Swiper的代码都可以通过回调触发:
<head> <script> window.viewWidth = window.innerWidth; // 全局暴露加载状态Promise,供后续逻辑调用 window.swiperLoader = new Promise((resolve) => { if (window.viewWidth < 480) { resolve(false); return; } const swiperJS = document.createElement('script'); swiperJS.type = "text/javascript"; swiperJS.src = "https://cdnjs.cloudflare.com/ajax/libs/Swiper/7.2.0/swiper-bundle.min.js"; swiperJS.onload = () => resolve(true); document.head.appendChild(swiperJS); }) </script> </head> <body> <script> window.swiperLoader.then(needInit => { if (needInit) { const swiper = new Swiper('.swiper'); // 其他依赖Swiper的逻辑都可以写在这里 } }) </script> </body>
注意事项
- 可以给
script标签加onerror回调处理加载失败的降级场景 - 动态脚本的
async属性默认是true,如果你需要同步加载可以手动设置swiperJS.async = false,但会阻塞页面渲染,不推荐使用
内容的提问来源于stack exchange,提问作者intheburrows
相关产品推荐
相关产品推荐

