有的时候需要动态加载 JavaScript 文件, 并且在加载成功后执行回调函数. 要实现这样的功能, 可以使用 < script> 元素的 load 事件 (IE9+,Chrome,Firefox 等) 和 onreadystatechange 事件(IE8 以下)
当你只需要加载一个 JS 文件时, 可以使用这段代码:
- function loadScript(src, callback) {
- var script = document.createElement('script'),
- head = document.getElementsByTagName('head')[0];
- script.type = 'text/javascript';
- script.charset = 'UTF-8';
- script.src = src;
- if (script.addEventListener) {
- script.addEventListener('load', function () {
- callback();
- }, false);
- } else if (script.attachEvent) {
- script.attachEvent('onreadystatechange', function () {
- var target = Windows.event.srcElement;
- if (target.readyState == 'loaded') {
- callback();
- }
- });
- }
- head.appendChild(script);
- }
- // 调用
- loadScript('http://cdn.staticfile.org/jquery/1.6.2/jquery.min.js',function(){
- console.log('onload');
- });
当你需要加载多个 JS 文件时:
- function loadScript(src, callback) {
- arraySync(function (one, i, c) {
- var cur_script = document.createElement("script");
- cur_script.type = 'text/javascript';
- cur_script.charset = 'UTF-8';
- cur_script.src = one;
- cur_script.addEventListener('load', function () {
- c(0, {
- i: i,
- v: {}
- });
- }, false);
- document.head.appendChild(cur_script)
- }, src, function (err, r) {
- // 全部加载完成后执行的回调函数
- if (err) {
- dhtmlxAlert(err.message);
- } else {
- callback()
- }
- });
- }
- // 处理异步, 不用 promise 的方案
- function arraySync(bsFunc, ar) {
- var callback = arguments[arguments.length - 1];
- if (ar.length == 0) {
- callback(0, []);
- return;
- }
- var sendErr = false;
- var finishNum = ar.length;
- var result = [];
- var args = [0, 0];
- for (var index = 2; index < arguments.length - 1; ++index) {
- args.push(arguments[index]);
- }
- args.push(function (err, r) {
- if (err) {
- if (!sendErr) {
- sendErr = true;
- callback(err);
- }
- return;
- }
- --finishNum;
- result[r.i] = r.v;
- if (finishNum == 0) {
- callback(0, result);
- }
- });
- for (var i = 0; i < ar.length; ++i) {
- args[0] = ar[i];
- args[1] = i;
- bsFunc.apply(null, args);
- }
- };
- // 调用
- loadScript(['./jquery.min.js','./echarts.min.js','./vue.min.js'],function(){
- console.log('onload');
- });
上述代码使用了 arraySync 方案来处理异步, 如果条件允许, 你也可以使用 promise 来解决, 效果都是一样的.
我的项目中是需要从 JSON 文件中读取配置, 取到的数据中有需要动态加载的 JS 列表, 然后使用上述的批量加载 JS 函数进行处理, 下面给出整体代码, 有需要的可以搭配使用哦~
- var loadScript = function (callback) {
- // 读取 JSON
- var request = new XMLHttpRequest();
- request.open("get", "package.json");
- request.send(null);
- request.onload = function () {
- if (request.status == 200) {
- var package = JSON.parse(request.responseText);
- // 合并 dependencies 和 plugins 对象
- Object.assign(package.dependencies, package.plugins);
- var scriptUrls = [];
- for (var i in package.dependencies) {
- scriptUrls.push(package.dependencies[i])
- }
- // 异步载入 script
- arraySync(function (one, i, c) {
- var cur_script = document.createElement("script");
- cur_script.type = 'text/javascript';
- cur_script.charset = 'UTF-8';
- cur_script.src = one;
- cur_script.addEventListener('load', function () {
- c(0, {
- i: i,
- v: {}
- });
- }, false);
- document.head.appendChild(cur_script)
- }, scriptUrls, function (err, r) {
- if (err) {
- dhtmlxAlert(err.message);
- } else {
- callback()
- }
- });
- }
- }
- }
- // 处理异步, 不用 promise 的方案
- function arraySync(bsFunc, ar) {
- var callback = arguments[arguments.length - 1];
- if (ar.length == 0) {
- callback(0, []);
- return;
- }
- var sendErr = false;
- var finishNum = ar.length;
- var result = [];
- var args = [0, 0];
- for (var index = 2; index < arguments.length - 1; ++index) {
- args.push(arguments[index]);
- }
- args.push(function (err, r) {
- if (err) {
- if (!sendErr) {
- sendErr = true;
- callback(err);
- }
- return;
- }
- --finishNum;
- result[r.i] = r.v;
- if (finishNum == 0) {
- callback(0, result);
- }
- });
- for (var i = 0; i < ar.length; ++i) {
- args[0] = ar[i];
- args[1] = i;
- bsFunc.apply(null, args);
- }
- };
来源: http://www.jianshu.com/p/997818dbf339