在JS中动态加载JS

时间:2013-01-25 11:42:12

标签: javascript jquery

我有一个动态网页,我需要在另一个javascript文件中导入外部JS文件(在IF条件下)。

我试图寻找一个可行的解决方案,但它没有用。

我尝试使用document.createElement()将JS文件加载到DOM,但它也无效。显然,Js已加载到DOM中,但在当前的JS文件中无法访问。

jQuery中的解决方案也没问题

13 个答案:

答案 0 :(得分:459)

我的猜测是,在你的DOM解决方案中,你做了类似的事情:

var script = document.createElement('script');
script.src = something;
//do stuff with the script

首先,这不起作用,因为脚本未添加到文档树中,因此不会加载。此外,即使你这样做,在加载另一个脚本时也会继续执行javascript,因此在该脚本完全加载之前,它的内容将无法使用。

您可以收听脚本的load事件,并按照您的意愿对结果执行操作。所以:

var script = document.createElement('script');
script.onload = function () {
    //do stuff with the script
};
script.src = something;

document.head.appendChild(script); //or something of the likes

答案 1 :(得分:120)

jQuery' s $.getScript()有时会出错,所以我使用自己的实现方式:

jQuery.loadScript = function (url, callback) {
    jQuery.ajax({
        url: url,
        dataType: 'script',
        success: callback,
        async: true
    });
}

并使用它:

if (typeof someObject == 'undefined') $.loadScript('url_to_someScript.js', function(){
    //Stuff to do after someScript has loaded
});

答案 2 :(得分:67)

我需要经常这样做,所以我用这个:

var loadJS = function(url, implementationCode, location){
    //url is URL of external file, implementationCode is the code
    //to be called from the file, location is the location to 
    //insert the <script> element

    var scriptTag = document.createElement('script');
    scriptTag.src = url;

    scriptTag.onload = implementationCode;
    scriptTag.onreadystatechange = implementationCode;

    location.appendChild(scriptTag);
};
var yourCodeToBeCalled = function(){
//your code goes here
}
loadJS('yourcode.js', yourCodeToBeCalled, document.body);

有关详细信息,请参阅此网站How do I include a JavaScript file in another JavaScript file?,这是我的功能想法的来源。

答案 3 :(得分:21)

您可以动态加载页面内的js而不是另一个js文件

您必须使用getScript加载js文件

$.getScript("ajax/test.js", function(data, textStatus, jqxhr) {
console.log(data); //data returned
console.log(textStatus); //success
console.log(jqxhr.status); //200
console.log('Load was performed.');
});

答案 4 :(得分:11)

Necromaning。

我用它来加载依赖脚本;
它可以与IE8 +一起使用,而不会像jQuery那样增加对另一个库的依赖!

var cScriptLoader = (function ()
{
    function cScriptLoader(files)
    {
        var _this = this;
        this.log = function (t)
        {
            console.log("ScriptLoader: " + t);
        };
        this.withNoCache = function (filename)
        {
            if (filename.indexOf("?") === -1)
                filename += "?no_cache=" + new Date().getTime();
            else
                filename += "&no_cache=" + new Date().getTime();
            return filename;
        };
        this.loadStyle = function (filename)
        {
            // HTMLLinkElement
            var link = document.createElement("link");
            link.rel = "stylesheet";
            link.type = "text/css";
            link.href = _this.withNoCache(filename);
            _this.log('Loading style ' + filename);
            link.onload = function ()
            {
                _this.log('Loaded style "' + filename + '".');
            };
            link.onerror = function ()
            {
                _this.log('Error loading style "' + filename + '".');
            };
            _this.m_head.appendChild(link);
        };
        this.loadScript = function (i)
        {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = _this.withNoCache(_this.m_js_files[i]);
            var loadNextScript = function ()
            {
                if (i + 1 < _this.m_js_files.length)
                {
                    _this.loadScript(i + 1);
                }
            };
            script.onload = function ()
            {
                _this.log('Loaded script "' + _this.m_js_files[i] + '".');
                loadNextScript();
            };
            script.onerror = function ()
            {
                _this.log('Error loading script "' + _this.m_js_files[i] + '".');
                loadNextScript();
            };
            _this.log('Loading script "' + _this.m_js_files[i] + '".');
            _this.m_head.appendChild(script);
        };
        this.loadFiles = function ()
        {
            // this.log(this.m_css_files);
            // this.log(this.m_js_files);
            for (var i = 0; i < _this.m_css_files.length; ++i)
                _this.loadStyle(_this.m_css_files[i]);
            _this.loadScript(0);
        };
        this.m_js_files = [];
        this.m_css_files = [];
        this.m_head = document.getElementsByTagName("head")[0];
        // this.m_head = document.head; // IE9+ only
        function endsWith(str, suffix)
        {
            if (str === null || suffix === null)
                return false;
            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }
        for (var i = 0; i < files.length; ++i)
        {
            if (endsWith(files[i], ".css"))
            {
                this.m_css_files.push(files[i]);
            }
            else if (endsWith(files[i], ".js"))
            {
                this.m_js_files.push(files[i]);
            }
            else
                this.log('Error unknown filetype "' + files[i] + '".');
        }
    }
    return cScriptLoader;
})();
var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();

如果您对用于创建此内容的typescript版本感兴趣:

class cScriptLoader {
    private m_js_files: string[];
    private m_css_files: string[];
    private m_head:HTMLHeadElement;

    private log = (t:any) =>
    {
        console.log("ScriptLoader: " + t);
    }


    constructor(files: string[]) {
        this.m_js_files = [];
        this.m_css_files = [];
        this.m_head = document.getElementsByTagName("head")[0];
        // this.m_head = document.head; // IE9+ only


        function endsWith(str:string, suffix:string):boolean 
        {
            if(str === null || suffix === null)
                return false;

            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }


        for(var i:number = 0; i < files.length; ++i) 
        {
            if(endsWith(files[i], ".css"))
            {
                this.m_css_files.push(files[i]);
            }
            else if(endsWith(files[i], ".js"))
            {
                this.m_js_files.push(files[i]);
            }
            else
                this.log('Error unknown filetype "' + files[i] +'".');
        }

    }


    public withNoCache = (filename:string):string =>
    {
        if(filename.indexOf("?") === -1)
            filename += "?no_cache=" + new Date().getTime();
        else
            filename += "&no_cache=" + new Date().getTime();

        return filename;    
    }


    public loadStyle = (filename:string) =>
    {
        // HTMLLinkElement
        var link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = this.withNoCache(filename);

        this.log('Loading style ' + filename);
        link.onload = () =>
        {
            this.log('Loaded style "' + filename + '".');

        };

        link.onerror = () =>
        {
            this.log('Error loading style "' + filename + '".');
        };

        this.m_head.appendChild(link);
    }


    public loadScript = (i:number) => 
    {
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = this.withNoCache(this.m_js_files[i]);

        var loadNextScript = () => 
        {
            if (i + 1 < this.m_js_files.length)
            {
                this.loadScript(i + 1);
            }
        }

        script.onload = () =>
        {
            this.log('Loaded script "' + this.m_js_files[i] + '".');
            loadNextScript();
        };


        script.onerror = () =>
        {
            this.log('Error loading script "' + this.m_js_files[i] + '".');
            loadNextScript();
        };


        this.log('Loading script "' + this.m_js_files[i] + '".');
        this.m_head.appendChild(script);
    }

    public loadFiles = () => 
    {
        // this.log(this.m_css_files);
        // this.log(this.m_js_files);

        for(var i:number = 0; i < this.m_css_files.length; ++i)
            this.loadStyle(this.m_css_files[i])

        this.loadScript(0);
    }

}


var ScriptLoader = new cScriptLoader(["foo.css", "Scripts/Script4.js", "foobar.css", "Scripts/Script1.js", "Scripts/Script2.js", "Scripts/Script3.js"]);
ScriptLoader.loadFiles();

如果要加载动态脚本列表,请将脚本写入属性,例如data-main,例如, <script src="scriptloader.js" data-main="file1.js,file2.js,file3.js,etc." ></script>
并做一个element.getAttribute("data-main").split(',')

,例如

var target = document.currentScript || (function() {
  var scripts = document.getElementsByTagName('script');
  // Note: this is for IE as IE doesn't support currentScript
  // this does not work if you have deferred loading with async
  // e.g. <script src="..." async="async" ></script>
  // https://web.archive.org/web/20180618155601/https://www.w3schools.com/TAgs/att_script_async.asp
  return scripts[scripts.length - 1];
})();

target.getAttribute("data-main").split(',')

获取清单。

答案 5 :(得分:7)

jQuery.getScript() 方法是Ajax函数的简写(使用dataType属性:$.ajax({ url: url, dataType: "script" {{1 }})

如果您希望脚本可以缓存,请使用RequireJS或按照jQuery的示例扩展})方法,类似于以下内容。

jQuery.getScript

参考:jQuery.getScript() | jQuery API Documentation

答案 6 :(得分:4)

你可以使用JQuery来做到这一点:

$.getScript("ajax/test.js", function(data, textStatus, jqxhr) {
  console.log(data); //data returned
  console.log(textStatus); //success
  console.log(jqxhr.status); //200
  console.log('Load was performed.');
});

此链接应该有所帮助: http://api.jquery.com/jQuery.getScript/

答案 7 :(得分:4)

我建议使用带有AMD javascript类文件的requirejs

这里如何使用它的好例子

http://www.sitepoint.com/understanding-requirejs-for-effective-javascript-module-loading/

答案 8 :(得分:3)

jQuery有$.getScript()

  

说明:使用GET HTTP请求从服务器加载JavaScript文件,然后执行。

答案 9 :(得分:3)

要创作我的插件,我需要在JS文件中加载外部脚本和样式,所有这些都是预定义的。为此,我做了以下事情:

    this.loadRequiredFiles = function (callback) {
        var scripts = ['xx.js', 'yy.js'];
        var styles = ['zz.css'];
        var filesloaded = 0;
        var filestoload = scripts.length + styles.length;
        for (var i = 0; i < scripts.length; i++) {
            log('Loading script ' + scripts[i]);
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = scripts[i];
            script.onload = function () {
                log('Loaded script');
                log(this);
                filesloaded++;  // (This means increment, i.e. add one)
                finishLoad();
            };
            document.head.appendChild(script);
        }
        for (var i = 0; i < styles.length; i++) {
            log('Loading style ' + styles[i]);
            var style = document.createElement('link');
            style.rel = 'stylesheet';
            style.href = styles[i];
            style.type = 'text/css';
            style.onload = function () {
                log('Loaded style');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(style);
        }
        function finishLoad() {
            if (filesloaded === filestoload) {
                callback();
            }
        }
    };

上下文中的更多脚本:

function myPlugin() {

    var opts = {
        verbose: false
    };                          ///< The options required to run this function
    var self = this;            ///< An alias to 'this' in case we're in jQuery                         ///< Constants required for this function to work

    this.getOptions = function() {
        return opts;
    };

    this.setOptions = function(options) {
        for (var x in options) {
            opts[x] = options[x];
        }
    };

    /**
     * @brief Load the required files for this plugin
     * @param {Function} callback A callback function to run when all files have been loaded
     */
    this.loadRequiredFiles = function (callback) {
        var scripts = ['xx.js', 'yy.js'];
        var styles = ['zz.css'];
        var filesloaded = 0;
        var filestoload = scripts.length + styles.length;
        for (var i = 0; i < scripts.length; i++) {
            log('Loading script ' + scripts[i]);
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = scripts[i];
            script.onload = function () {
                log('Loaded script');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(script);
        }
        for (var i = 0; i < styles.length; i++) {
            log('Loading style ' + styles[i]);
            var style = document.createElement('link');
            style.rel = 'stylesheet';
            style.href = styles[i];
            style.type = 'text/css';
            style.onload = function () {
                log('Loaded style');
                log(this);
                filesloaded++;
                finishLoad();
            };
            document.head.appendChild(style);
        }
        function finishLoad() {
            if (filesloaded === filestoload) {
                callback();
            }
        }
    };

    /**
     * @brief Enable user-controlled logging within this function
     * @param {String} msg The message to log
     * @param {Boolean} force True to log message even if user has set logging to false
     */
    function log(msg, force) {
        if (opts.verbose || force) {
            console.log(msg);
        }
    }

    /**
     * @brief Initialise this function
     */
    this.init = function() {
        self.loadRequiredFiles(self.afterLoadRequiredFiles);
    };

    this.afterLoadRequiredFiles = function () {
        // Do stuff
    };

}

答案 10 :(得分:0)

您可以使用jQuery的$.getScript()方法来执行此操作,但如果您想要更全面的功能,yepnope.js是您的选择。它支持脚本和样式表的条件加载,并且易于使用。

答案 11 :(得分:0)

这是一个动态加载javascript和CSS文件的小lib:

https://github.com/todotresde/javascript-loader

我认为按顺序和动态加载css和js文件很有用。

支持扩展以加载您想要的任何lib,而不仅仅是主文件,您可以使用它来加载自定义文件。

即:

<html>
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="scripts/javascript-loader.js" type="text/javascript" charset="utf-8" ></script>    
    <script type="text/javascript">
        $(function() {

            registerLib("threejs", test);

            function test(){
                console.log(THREE);
            }

            registerLib("tinymce", draw);

            function draw(){
                tinymce.init({selector:'textarea'});
            }

        }); 
    </script>
</head>
<body>
    <textarea>Your content here.</textarea>
</body>

答案 12 :(得分:0)

如果依赖 多个文件,请使用AMD / RequireJS。 http://requirejs.org/