动态加载脚本:innerHTML与appendChild的加载差异问题
为什么用innerHTML添加的script标签不会加载外部脚本?
嗨,这个问题我之前也碰到过,当时盯着DOM结构看了半天——明明script标签好好躺在那里,就是不加载对应的.js文件,属实让人疑惑!其实这是浏览器的既定解析规则,不是你的代码出了错。
核心原因
浏览器在处理通过innerHTML插入的HTML内容时,会刻意跳过<script>标签的执行和外部资源加载流程。这是出于安全考量:如果允许innerHTML随意触发脚本加载,很容易被恶意利用来注入危险代码。哪怕你写的是完全合法的脚本地址,浏览器也只会把这个script标签当作普通DOM节点插入,不会发起资源下载请求。
而appendChild是直接操作DOM节点的原生API,当你用它把手动创建的<script>元素添加到DOM时,浏览器会遵循正常的DOM节点处理逻辑:检测到这是一个带src属性的脚本标签,就会自动发起HTTP请求去加载对应的文件。
直观代码对比
举个例子,你用innerHTML的写法:
// 不会加载脚本,仅插入空的script节点 document.querySelector('#app').innerHTML = '<script src="utils.js"></script>';
换成appendChild就会正常工作:
// 会自动加载并执行utils.js const scriptEl = document.createElement('script'); scriptEl.src = 'utils.js'; document.querySelector('#app').appendChild(scriptEl);
折中方案(如果偏好innerHTML批量插入)
如果你的场景需要批量插入大量HTML内容,其中包含脚本标签,可以先插入innerHTML内容,再手动提取脚本信息创建真实节点:
// 先插入完整HTML结构(包含未生效的script标签) document.querySelector('#app').innerHTML = ` <div class="page-content">这里是页面内容</div> <script src="init.js"></script> `; // 手动提取脚本信息,创建可加载的script节点 const dummyScript = document.querySelector('#app script'); const realScript = document.createElement('script'); realScript.src = dummyScript.src; document.body.appendChild(realScript); // 移除DOM里的空脚本标签 dummyScript.remove();
不过这种方法有点绕,其实最稳妥、最直观的还是单独用appendChild来处理脚本加载~
内容的提问来源于stack exchange,提问作者Ashe Austaire
相关产品推荐
相关产品推荐

