You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决Jquery、Bootstrap渲染阻塞及动态加载JS依赖顺序问题

解决脚本渲染阻塞与依赖加载顺序问题

首先,咱们先搞清楚你当前代码出问题的核心原因:你现在是一次性把所有脚本标签添加到页面中,浏览器会并行下载这些脚本文件,而且执行顺序不一定严格按照你数组里的顺序(尤其是不同脚本的下载速度不同时)。这就导致依赖jQuery的脚本(比如Bootstrap、utility.min.js这些)可能在jQuery还没加载执行完成时就先跑起来了,自然会报jQuery is not defined这类错误。

要解决这个问题,核心是要保证脚本按顺序加载并执行——也就是先完全加载并执行jQuery,再加载Bootstrap,接着再加载后续依赖它们的脚本。下面给你两种可行的方案:

方案1:递归式顺序加载(兼容旧浏览器)

这个方案用递归的方式,每次只加载一个脚本,等当前脚本加载完成后再加载下一个,完美保证依赖顺序:

var sources = [ 
  "common/scripts/external/jquery-3.2.1.min.js", 
  "common/scripts/external/bootstrap.min.js", 
  "common/scripts/other/utility.min.js?v=1.0.0", 
  "common/scripts/external/jquery.ui.widget.min.js", 
  "common/scripts/external/jquery.fileupload.min.js", 
  "common/scripts/external/jquery.fileupload-process.min.js", 
  "common/scripts/external/jquery.fileupload-validate.min.js", 
  "common/scripts/external/jquery.knob.min.js", 
  "common/scripts/external/jquery.payform.min.js" 
];

// 递归加载脚本,index为当前要加载的脚本下标
function loadScript(index) {
  // 所有脚本加载完成,终止递归
  if (index >= sources.length) return;
  
  var scriptElement = document.createElement("script");
  scriptElement.src = sources[index];
  
  // 当前脚本加载完成后,加载下一个
  scriptElement.onload = function() {
    loadScript(index + 1);
  };
  
  // 可选:处理脚本加载失败的情况
  scriptElement.onerror = function() {
    console.error(`加载脚本失败:${sources[index]}`);
    loadScript(index + 1); // 可根据需求调整,比如失败后停止加载
  };
  
  document.body.appendChild(scriptElement);
}

// 页面加载完成后启动加载流程
if (window.addEventListener) {
  window.addEventListener("load", function() {
    loadScript(0);
  }, false);
} else if (window.attachEvent) {
  window.attachEvent("onload", function() {
    loadScript(0);
  });
} else {
  window.onload = function() {
    loadScript(0);
  };
}

方案2:Promise链式加载(现代浏览器友好)

如果你不需要兼容特别老旧的浏览器,用Promise来实现顺序加载会更清晰,还能方便处理整体加载成功/失败的情况:

var sources = [ 
  "common/scripts/external/jquery-3.2.1.min.js", 
  "common/scripts/external/bootstrap.min.js", 
  "common/scripts/other/utility.min.js?v=1.0.0", 
  "common/scripts/external/jquery.ui.widget.min.js", 
  "common/scripts/external/jquery.fileupload.min.js", 
  "common/scripts/external/jquery.fileupload-process.min.js", 
  "common/scripts/external/jquery.fileupload-validate.min.js", 
  "common/scripts/external/jquery.knob.min.js", 
  "common/scripts/external/jquery.payform.min.js" 
];

// 封装单个脚本加载为Promise
function loadSingleScript(src) {
  return new Promise(function(resolve, reject) {
    var script = document.createElement('script');
    script.src = src;
    script.onload = resolve;
    script.onerror = reject;
    document.body.appendChild(script);
  });
}

// 按顺序加载所有脚本
function loadScriptsInOrder(scriptList) {
  return scriptList.reduce(function(prevPromise, currentSrc) {
    return prevPromise.then(function() {
      return loadSingleScript(currentSrc);
    });
  }, Promise.resolve());
}

// 页面加载完成后启动加载
if (window.addEventListener) {
  window.addEventListener("load", function() {
    loadScriptsInOrder(sources)
      .then(function() {
        console.log("所有脚本加载完成!");
      })
      .catch(function(error) {
        console.error("脚本加载出错:", error);
      });
  }, false);
} else if (window.attachEvent) {
  window.attachEvent("onload", function() {
    loadScriptsInOrder(sources)
      .then(function() {
        console.log("所有脚本加载完成!");
      })
      .catch(function(error) {
        console.error("脚本加载出错:", error);
      });
  });
} else {
  window.onload = function() {
    loadScriptsInOrder(sources)
      .then(function() {
        console.log("所有脚本加载完成!");
      })
      .catch(function(error) {
        console.error("脚本加载出错:", error);
      });
  };
}

额外优化建议

  • 如果你想更早开始加载脚本,不用等页面所有资源(比如图片)加载完成,可以把window.load事件换成DOMContentLoaded事件——这个事件会在页面DOM结构构建完成后就触发,能提前启动脚本加载,提升用户体验。
  • 如果你后续考虑合并脚本,把jQuery、Bootstrap和依赖它们的脚本打包成一个文件,也能从根本上解决顺序问题,同时减少HTTP请求数,进一步优化加载速度。

内容的提问来源于stack exchange,提问作者OM The Eternity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:47:27