美文网首页让前端飞Web前端之路超有趣的JS
原生JS实现动态批量加载js文件

原生JS实现动态批量加载js文件

作者: Nanayai | 来源:发表于2019-07-21 00:59 被阅读71次

    有的时候需要动态加载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 = window.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);
        }
    };
    

    相关文章

      网友评论

        本文标题:原生JS实现动态批量加载js文件

        本文链接:https://www.haomeiwen.com/subject/soyklctx.html