为何HTML无法调用JS中的main()函数?ES模块引入场景问题
问题:body onload调用main()失败,移除import语句就正常
当通过<body onload="main()">调用script.js里的main()函数时,函数完全没执行。但删掉script.js里的import语句后,main()就能正常触发。现在必须保留import来引入createNewScreen(),怎么解决?
相关代码
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Demo</title> <script src="js/script.js"></script> </head> <body onload="main()"> <div id="allScreen"> </div> </body> </html>
script.js
import { createNewScreen } from "./createScreen"; let screens = []; function main(){ screens.push(createNewScreen()); document.getElementById('allScreen').appendChild(screens[0]); }
createScreen.js
export function createNewScreen(){ let screen = document.createElement('div'); screen.style.width = '500px'; screen.style.height = '300px'; screen.style.backgroundColor = 'orange'; return screen; }
问题原因
一旦脚本里使用了import/export语法,浏览器会自动把这个脚本当作ES模块处理。ES模块的作用域是独立的,里面的变量和函数默认不会暴露到全局作用域。而<body onload="main()">是在全局作用域中查找main函数,自然找不到,所以不会执行。
解决方案
方案1:标记脚本为模块,在代码内监听加载事件(推荐)
这是最规范的做法,不会污染全局作用域。
- 修改index.html中的script标签,添加
type="module"属性:
<script src="js/script.js" type="module"></script>
- 删除
<body>标签的onload属性,在script.js里手动监听页面加载事件:
import { createNewScreen } from "./createScreen"; let screens = []; function main(){ screens.push(createNewScreen()); document.getElementById('allScreen').appendChild(screens[0]); } // 监听页面所有资源加载完成 window.addEventListener('load', main);
如果不需要等待图片等资源加载完成,用DOMContentLoaded会更高效:
document.addEventListener('DOMContentLoaded', main);
方案2:把main函数挂载到全局作用域(应急可用)
如果一定要保留<body onload="main()">的写法,可以把main强制挂载到window对象上,暴露到全局:
修改script.js:
import { createNewScreen } from "./createScreen"; let screens = []; function main(){ screens.push(createNewScreen()); document.getElementById('allScreen').appendChild(screens[0]); } // 将main挂载到全局作用域 window.main = main;
同时记得给script标签加上type="module":
<script src="js/script.js" type="module"></script>
这样<body onload="main()">就能找到全局的main函数了。
内容的提问来源于stack exchange,提问作者codeWcay
相关产品推荐
相关产品推荐

