动态添加JavaScript文件的方法在页面中

38

我看到Scriptaculous.js文件可以动态地包含其所需的JavaScript文件。是否有更好的方法来动态地包含JavaScript?

例如,我想像这样包含我的js文件,

<script src="single.js?files=first.js,second.js,third.js..."></script>

我该如何以高效的方式实现这个?


5
为什么会有负面投票?它有什么问题吗? - Nazmul
@Hoque - 看起来有人正在浏览问题页面并对所有内容进行投票否决;至少有5个问题的得分为-1或更低。我猜一个管理员可以验证这一点... - John Rasch
2
同意,我也很好奇发生了什么。看起来有些垃圾邮件发送者在玩乐。所以...+1来弥补一下。 - Damb
我想知道这里有三个答案,但我只得到了两个。发生了什么事? - Nazmul
可能是JQuery动态加载Javascript文件的重复问题。 - Michał Perłakowski
显示剩余2条评论
9个回答

46

动态加载.js或.css文件,简而言之,就是使用DOM方法首先创建一个时髦的新“SCRIPT”或“LINK”元素,分配相应的属性,最后使用element.appendChild()将元素添加到文档树中所需的位置。听起来比实际情况要复杂得多。让我们看看它是如何运作的:

function loadjscssfile(filename, filetype){
 if (filetype=="js"){ //if filename is a external JavaScript file
  var fileref=document.createElement('script')
  fileref.setAttribute("type","text/javascript")
  fileref.setAttribute("src", filename)
 }
 else if (filetype=="css"){ //if filename is an external CSS file
  var fileref=document.createElement("link")
  fileref.setAttribute("rel", "stylesheet")
  fileref.setAttribute("type", "text/css")
  fileref.setAttribute("href", filename)
 }
 if (typeof fileref!="undefined")
  document.getElementsByTagName("head")[0].appendChild(fileref)
}

loadjscssfile("myscript.js", "js") //dynamically load and add this .js file
loadjscssfile("javascript.php", "js") //dynamically load "javascript.php" as a JavaScript file
loadjscssfile("mystyle.css", "css") ////dynamically load and add this .css file

我希望它有用


非常感谢您的努力。这就像逐个添加脚本一样。 - Nazmul
2
浏览器支持情况如何? - Pacerier
你需要添加 document.body.appendChild(fileref); 让它在浏览器中运行。 - Siddharth
请注意,文件可能无法按照您调用它们的确切顺序加载(和运行)。 - kevnk
如果您有一些document.ready()内联工作,那么document.getElementsByTagName("head")[0].appendChild(fileref)无法正常运行。$("head").append(fileref);对我来说非常有效,尽管它需要jquery.min.js内联引用。 - AmirHossein Manian

13

您可以使用 jQuery.getScript() 函数... 我认为使用这个函数来引入 JavaScript 的 .js 文件会更容易。

这里 是参考链接。


1
我认为这是我在SO上所有链接中要使用的文本。 - sdleihssirhc

4

按照Salaman A的评论建议,我找到了Google Analytics现在的做法: https://developers.google.com/analytics/devguides/collection/gajs/asyncTracking

这里是同样代码的更通用版本:

(function() {
    var s = document.createElement('script'); // Create a script element
    s.type = "text/javascript";               // optional in html5
    s.async = true;                           // asynchronous? true/false
    s.src = "//example.com/your_script.js"; 
    var fs = document.getElementsByTagName('script')[0];  // Get the first script
    fs.parentNode.insertBefore(s, fs);
})();

3

编辑:不要使用这种方法 - 我在十年前写了这个答案!

仅供记录,不建议使用。


有许多不同的方法,但 Google 加载附加脚本的方式是这样的:

function getScript(src) {
    document.write('<' + 'script src="' + src + '"' +
                   ' type="text/javascript"><' + '/script>');
}

这段内容直接来自Google地图加载器。

将脚本标签直接写入文档是最简单、最高效的方法。


4
谷歌不再推荐这样做了 :) 例如,他们改变了添加谷歌分析代码到网站的推荐方式。 - Salman A
1
你能提供一个链接来证明这一点吗?因为所有的谷歌API都是通过这种方式加载的,甚至包括http://code.google.com/apis/loader/。 - herostwist
2
这里有一个程序相关的内容:使用传统的片段。请阅读介绍段落,其中建议您使用默认跟踪代码片段,该片段在“跟踪网站”中进行了描述。传统的脚本(更准确地说是脚本加载器)使用document.write,更新的脚本则使用document.createElement。这里还有另外一篇有趣的阅读材料:避免使用document.write - Salman A
2
哈哈,感谢你在三年半后给我点了个踩 - 毫不奇怪的是,自从我写下这个答案以来,事情已经发生了变化。 - herostwist
@herostwist,你需要定期更新你发布的每一个回答!!其他人都这样做哈哈哈:P - GôTô
显示剩余2条评论

2
创建一个脚本标签,设置URL,将其添加到文档中:
var script = document.createElement("script");
script.src = "https://example.com/your_script.js"; 
document.body.appendChild(script);

这就是答案了。对于如此简单的任务,这个页面上有太多过于复杂的答案。
如果您正在使用现代JavaScript,您可以使用动态导入,语法类似于await import(...)。这超出了本答案的范围,但您可以在这里阅读更多相关信息。

为什么要将内容添加到body而不是head - undefined

1
动态添加新的JavaScript文件:
function includeJS(jsFile) {
    $('head').append($('<script>').attr('type', 'text/javascript').attr('src', jsFile));
}


// Pick a JS to load
if ($.browser.msie) {
    includeJS('first.js');
} else {
    includeJS('second.js');
}
includeJS('third.js');

5
如果您已经加载了jQuery,只需使用jQuery.getScript()即可。 - Richard

1
我看过scriptaculous的加载器做了什么。它会遍历文档中所有的脚本标签,找到自己加载的那个标签,例如:
<script src="/path/to/single.js?files=first.js,second.js,third.js"></script>

然后它解析了src属性中使用的查询字符串,并为每个脚本文件动态创建额外的script标记。同时,它还解析了基础脚本的路径(/path/to/single.js),并使用相同的路径加载依赖文件(例如/path/to/first.js)。

您可以像这样创建自己的脚本加载器。在原生JavaScript中,您可以使用以下函数:

Anand Thangappan发布了一个使用这些函数的解决方案。如果您正在使用jQuery或MooTools等框架,则两者都提供了自己的动态加载JavaScript的实现。

最后,有一个服务器端的解决方案可以解决你的问题。看看minify -- 将多个CSS或JavaScript文件合并和压缩成一个下载。


1
如果您在文档中有一些内联的document.ready()工作,那么 document.getElementsByTagName("head")[0].appendChild(fileref‌​) 将无法正常工作。对我来说,$("head").append(fileref); 运行良好,虽然需要内联引用 jquery.min.js
<head>
    <!-- Meta, title, CSS, favicons, etc. -->
    <script src="script/jquery.min.js"></script>
    <script src="script/master_load.js"></script>
    <script>
        load_master_css();
        load_master_js();
    </script>
</head>

master_load.js 相关:

function loadjscssfile(filename) {
    if (filename.substr(filename.length - 4) == ".css") { // 'endsWith' is not IE supported.
        var fileref = document.createElement("link")
        fileref.setAttribute("rel", "stylesheet")
        fileref.setAttribute("href", filename)
        //fileref.setAttribute("type", "text/css")
    }
    else if (filename.substr(filename.length - 3) == ".js") {
        var fileref = document.createElement('script')
        fileref.setAttribute("src", filename)
        //fileref.setAttribute("type", "text/javascript")
    }
    $("head").append(fileref);
}
function load_master_css() {
    loadjscssfile("css/bootstrap.min.css");
    // bunch of css files
}
function load_master_js() {
    loadjscssfile("script/bootstrap.min.js");
    // bunch of js files
}

0
我们可以快速扩展这个功能,以便在脚本添加后执行回调。
function loadjscssfile(filename, filetype, callback){
    if (typeof fileref!="undefined") {
        document.getElementsByTagName("head")[0].appendChild(fileref);
        callback();
    }
}

我怀疑这根本不起作用...你传递了filenamefiletype,但你没有使用它们,而使用了你没有声明的fileref - GôTô
抱歉,我的评论是针对Anand Thangappan上面的答案。我本以为我已经将其作为评论而不是新回答发表了。 - Dennis Bartlett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接