如何通过JavaScript文件包含目录中的所有JavaScript文件?

50

我有很多JavaScript文件想要引入到网页中,但我不想一直写

<script type="text/javascript" src="js/file.js"></script>

那么有没有一种方法可以包含目录中的所有文件(大小未知)? 我能做类似于...

$.getScript("js/*.js");

如何使用jQuery获取“js”目录中的所有JavaScript文件?

10个回答

30
一般来说,这可能不是一个好主意,因为您的 HTML 文件应该只加载它们实际使用的 JS 文件。无论如何,使用任何服务器端脚本语言都可以轻松实现此目的。只需在向客户端提供页面之前插入脚本标记即可。
如果您想在不使用服务器端脚本的情况下完成此操作,您可以将 JS 文件放入允许列出目录内容的目录中,然后使用 XMLHttpRequest 读取目录内容,并解析出文件名并加载它们。
第三个选项是使用 getScript() 的“加载器”JS 文件来加载所有其他文件。将其放入所有 HTML 文件的脚本标记中,然后每当上传新脚本时,只需要更新加载器文件即可。

我认为这是实现OP想要的功能的唯一方法,而不需要服务器端脚本。但我同意,最好避免使用它。 - harpo
我喜欢选项#3,也同意它不是一个好的选择。但是,我想先让它工作起来 :) 那么,我该如何使用.getScript()来获取目录中的所有文件呢?你能提供一些代码吗? - Hristo
Hristo,我的意思是你可以为目录中的每个JavaScript文件都调用一次getScrip(),然后每次添加新文件时都添加一个新条目。 - Mark Bessey
4
水母树,我觉得你没有理解我的意思——如果原帖中将所有的JS文件放在一个名为“scripts”的目录中,那么HTML页面上的JavaScript代码只需要发起一个指向"http://example.com/scripts/"的XmlHttpRequest请求,服务器就会返回该目录下的文件列表。然后他们可以解析响应文本,逐个加载每个JS文件。 - Mark Bessey
即使只是为了好玩,这也很酷。它将允许开发人员将js文件拖放到js文件夹中,并像应用程序一样部署其函数。无需编写代码。如果可以使其正常工作,我可以看到一些很棒的应用程序。 - Adam Grant
@MarkBessey 注意,你可以编译文件依赖项而不是托管许多文件。这比加载多个文件要快。 - Loïc Faure-Lacroix

24

使用服务器端脚本生成脚本标签行如何?粗略地说,可以使用类似这样的代码(PHP) -

$handle = opendir("scripts/");

while (($file = readdir($handle))!== false) {
    echo '<script type="text/javascript" src="' . $file . '"></script>';
}

closedir($handle);

嗯...我希望这只是最后的选择。目前我不想使用PHP。 - Hristo
我认为这在Javascript中不可能实现,因为它无法访问任何文件系统。也许可以使用ActiveX对象,但用户可能不会喜欢这种方式。 - jellyfishtree

16

如果您希望使用100%客户端方案,理论上您可以这样做:

通过XmlHttpRequest获取该目录的目录列表页面(如果目录中没有index.html文件,则大多数Web服务器会返回文件列表)。

使用JavaScript解析该文件,提取所有.js文件。当然,这将对您的Web服务器/ Web主机的目录列表格式敏感。

使用类似以下内容的方式动态添加脚本标记:

function loadScript (dir, file) {
 var scr = document.createElement("script");
 scr.src = dir + file;
 document.body.appendChild(scr);
 }

另外,也可以使用FileReader从zip文件夹中加载文件 - Anderson Green

4

可以完全在客户端完成,但是所有的JavaScript文件名都必须指定。例如,作为数组项:

function loadScripts(){
   var directory = 'script/';
   var extension = '.js';
   var files = ['model', 'view', 'controller'];  
   for (var file of files){ 
       var path = directory + file + extension; 
       var script = document.createElement("script");
       script.src = path;
       document.body.appendChild(script);
   } 
 }

我喜欢你的Swift答案,并稍微调整了一下。我认为你需要将脚本添加到头部而不是正文中,谢谢。 - Hasan A Yousef

3

@jellyfishtree,如果你能创建一个包含所有js文件的php文件并且通过script标签将该php文件引入,那会更好。这样会提高性能,因为浏览器需要向服务器发送的请求较少。参考以下内容:

javascripts.php:

<?php
   //sets the content type to javascript 
   header('Content-type: text/javascript');

   // includes all js files of the directory
   foreach(glob("packages/*.js") as $file) {
      readfile($file);
   }
?>


index.php:

<script type="text/javascript" src="javascripts.php"></script>

就是这样!
玩得开心!:)


3
您可以使用类似Grunt Include Source的工具。它提供了一种很好的语法,可以预处理您的HTML文件,并包含任何您想要的内容。这也意味着,如果您正确设置构建任务,您可以在开发模式下拥有所有这些包含文件,但在生产模式下不会包含,这非常酷。
如果您的项目中没有使用Grunt,则可能有类似于Gulp或其他任务运行程序的工具。

1
如果今天问这个问题,这将是被接受的答案。 - tejas_spy007

2

在 JavaScript 中你无法这样做,因为 JS 是在浏览器中执行的,而不是在服务器中执行的,所以它不知道目录或其他服务器资源。

最好的选择是使用像 jellyfishtree 发布的服务器端脚本。


3
嗯,getScript需要指定脚本的路径,对吧?没有什么魔法。 - harpo
1
除非与一些服务器端脚本一起使用,否则无法从JS访问私有服务器资源。 它们在不同的位置执行(一个在客户端,另一个在服务器端)。 - Alberto Martinez

1

我正在寻找这个问题的答案,并且有自己的问题。我在不同的地方找到了几个解决方案,并将它们组合成了我自己喜欢的答案。

function exploreFolder(folderURL,options){
/* options:                 type            explaination

    **REQUIRED** callback:  FUNCTION        function to be called on each file. passed the complete filepath
    then:                   FUNCTION        function to be called after loading all files in folder. passed the number of files loaded
    recursive:              BOOLEAN         specifies wether or not to travel deep into folders
    ignore:                 REGEX           file names matching this regular expression will not be operated on
    accept:                 REGEX           if this is present it overrides the `ignore` and only accepts files matching the regex
*/
$.ajax({
    url: folderURL,
    success: function(data){
        var filesLoaded = 0,
        fileName = '';

        $(data).find("td > a").each(function(){
            fileName = $(this).attr("href");

            if(fileName === '/')
                return;  //to account for the (go up a level) link

            if(/\/\//.test(folderURL + fileName))
                return; //if the url has two consecutive slashes '//'

            if(options.accept){
                if(!options.accept.test(fileName))
                    //if accept is present and the href fails, dont callback
                    return;
            }else if(options.ignore)
                if(options.ignore.test(fileName))
                    //if ignore is present and the href passes, dont callback
                    return;

            if(fileName.length > 1 && fileName.substr(fileName.length-1) === "/")
                if(options.recursive)
                    //only recurse if we are told to
                    exploreFolder(folderURL + fileName, options);
                else
                    return;

            filesLoaded++;
            options.callback(folderURL + fileName);
            //pass the full URL into the callback function
        });
        if(options.then && filesLoaded > 0) options.then(filesLoaded);
    }
});
}

然后你可以这样调用它:
var loadingConfig = {
    callback: function(file) { console.log("Loaded file: " + file); },
    then: function(numFiles) { console.log("Finished loading " + numFiles + " files"); },
    recursive: true,
    ignore: /^NOLOAD/,
};
exploreFolder('/someFolderURL/', loadingConfig);

这个例子将在指定文件夹中调用回调函数,对于以NOLOAD开头的文件/文件夹除外。如果你想要将文件加载到页面中,那么可以使用我开发的另一个辅助函数。
function getFileExtension(fname){
    if(fname)
        return fname.substr((~-fname.lastIndexOf(".") >>> 0) + 2);
    console.warn("No file name provided");
}
var loadFile = (function(filename){
    var img = new Image();

    return function(){
        var fileref,
            filename = arguments[0],
            filetype = getFileExtension(filename).toLowerCase();

        switch (filetype) {
            case '':
                return;
            case 'js':
                fileref=document.createElement('script');
                fileref.setAttribute("type","text/javascript");
                fileref.setAttribute("src", filename);
                break;
            case "css":
                fileref=document.createElement("link");
                fileref.setAttribute("rel", "stylesheet");
                fileref.setAttribute("type", "text/css");
                fileref.setAttribute("href", filename);
                break;
            case "jpg":
            case "jpeg":
            case 'png':
            case 'gif':
                img.src = filename;
                break;
            default:
                console.warn("This file type is not supported: "+filetype);
                return;
        }
        if (typeof fileref !== undefined){
            $("head").append(fileref);
            console.log('Loaded file: ' + filename);
        }
    }
})();

此函数接受JS | CSS |(普通图像)文件并加载它。它还将执行JS文件。 在您的脚本中运行需要加载所有图像和样式表和其他脚本的完整调用可能如下所示:
loadingConfig = {
    callback: loadfile,
    then: function(numFiles) { console.log("Finished loading " + numFiles + " files"); },
    recursive: true,
    ignore: /^NOLOAD/,
};
exploreFolder('/someFolderURL/', loadingConfig);

它工作得非常出色!


唯一的限制是需要服务器发布其目录中文件的列表。如果禁用了服务器设置中的某个设置,则无法在没有服务器端代码的情况下获得所需内容。 - Frozenfrank
它还依赖于jQuery来加载文件列表(在exploreFolder内),然后加载文件(在loadFile内)。 - Frozenfrank

1
你不能从浏览器中使用Javascript来做到那一点... 如果我是你,我会使用类似 browserify 的工具。使用commonjs模块编写代码,然后将javascript文件编译成一个文件。
在你的html中加载编译后的javascript文件。

1
另一个相当简短的选项是:


<script type="text/javascript">
$.ajax({
  url: "/js/partials",
  success: function(data){
     $(data).find('a:contains(.js)').each(function(){
        // will loop through 
        var partial= $(this).attr("href");
        $.getScript( "/js/partials/" + partial, function( data, textStatus, jqxhr ) {});
     });
  }
});
</script>

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