是否可以使用requireJS“需要”整个文件夹。
例如,我有一个行为文件夹,其中包含大量行为js文件。我真的希望能够简单地使用require(['behavior / *'],function(){...});加载该文件夹中的所有内容,而不是必须使该列表保持最新。一旦压缩和优化,我就会把所有这些文件放在一起,但是对于开发来说,单独使用它们会更容易。
答案 0 :(得分:24)
浏览器中的javascript没有文件系统访问权限,因此无法扫描目录中的文件。如果您使用php或ruby等脚本语言构建应用程序,则可以编写一个扫描目录的脚本,并将文件名添加到require()调用中。
答案 1 :(得分:8)
虽然浏览器中的JavaScript不能(也不应该)看到文件系统,但我创建了一个Grunt任务,它将执行此操作。我现在还在努力在这里和那里触摸它,但欢迎你来看看。
https://npmjs.org/package/require-wild
npm install require-wild
在您的情况下,您所要做的就是设置任务的设置
grunt.initConfig({
requireWild: {
app: {
// Input files to look for wildcards (require|define)
src: ["./**/*.js"],
// Output file contains generated namespace modules
dest: "./namespaces.js",
// Load your require config file used to find baseUrl - optional
options: { requireConfigFile: "./main.js" }
}
}
});
grunt.loadNpmTasks("require-wild");
grunt.registerTask('default', ['requireWild']);
然后运行grunt任务。您的文件将被生成。修改您的main.js
以加载namespaces.js
require(['namespaces'], function () { ... });
因此现在允许src
下的模块使用与grunt的glob模式匹配的依赖关系。
require(['behaviors/**/*'], function (behaviors) { }
这种意识形态假设您有一个有意义的文件结构。
答案 2 :(得分:5)
我知道这已经过时了,但我想分享我的解决方案:
对于此解决方案,您需要JQuery
1)创建一个 bash脚本,列出所有js文件 “MyDirectory /”,将其保存到“directoryContents.txt”:
#!/bin/bash
#Find all the files in that directory...
for file in $( find MyDirectory/ -type f -name "*.js" )
do
fileClean=${file%.js} #Must remove .js from the end!
echo -n "$fileClean " >> MyDirectory/directoryContents.txt
done
MyDirectory / FirstJavascriptFile MyDirectory / SecondJavascriptFile mydirectory中/ ThirdJavascriptFile
2)然后在你的客户端JS代码:
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
//Done loading this one file
});
}
}, "text");
我遇到的问题是这段代码没有在我的其他代码之前完成,所以这是我的扩展答案:
define([''], function() {
return {
createTestMenu: function()
{
this.loadAllJSFiles(function(){
//Here ALL those files you need are loaded!
});
},
loadAllJSFiles: function(callback)
{
$.get( "MyDirectory/directoryContents.txt", {}, function( data ) {
var allJsFilesInFolder = data.split(" ");
var currentFileNum = 0;
for(var a=0; a<allJsFilesInFolder.length; a++)
{
require([allJsFilesInFolder[a]], function(jsConfig)
{
currentFileNum++;
//If it's the last file that needs to be loaded, run the callback.
if (currentFileNum==allJsFilesInFolder.length)
{
console.log("Done loading all configuration files.");
if (typeof callback != "undefined"){callback();}
}
});
}
}, "text");
}
}
});
我最终做的是每次我的Node服务器启动时,它都会运行bash脚本,填充directoryContents.txt。然后我的客户端只读取directoryContents.txt作为文件列表,并要求该列表中的每一个。
希望这有帮助!
答案 3 :(得分:1)
实际上没有办法在概念上做到这一点(我知道)。
虽然有一些解决方法:
使用grunt
和concat
然后只需要那个庞然大物......我知道,有点太糟糕了。
我认为更好的解决方案......使用需要的层次结构:
require('/js/controllers/init', function(ctrls){
ctrls(app, globals);
});
// /js/controllers/init.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
var indexModule = index(app, globals);
var indexModule = posts(app, globals);
return app || someModule;
};
});
// /js/controllers/index.js
define('js/controllers/index', 'js/controllers/posts', function(index, posts){
return function protagonist(app, globals){
function method1(){}
function method2(){}
return {
m1: method1,
m2: method2
};
};
});
请注意“protagonist
”function
。这允许您在使用之前初始化模块,因此现在您可以传递“sandbox
” - 在这种情况下app
和globals
。
实际上,你不会有/js/controllers/index.js
......它可能应该是/js/controllers/index/main.js
或/js/controllers/index/init.js
,因此有一个目录(兄弟){{1}称为“索引”。这将使您的模块可以扩展到给定的接口 - 您可以简单地交换模块并保持您的接口相同。
希望这有帮助!快乐的编码!
答案 4 :(得分:1)
我写了一个库来解决这个问题。最终有其他人出现并改进了我的图书馆,这里是:
https://github.com/smartprocure/directory-metagen
您可以将我的lib与Gulp一起使用 - 它会为您的项目生成元数据,而RequireJS可以使用该元数据来从文件系统中获取所需的文件。
使用此lib将生成一个如下所示的RequireJS模块:
define(
[
"text!app/templates/dashboardTemplate.ejs",
"text!app/templates/fluxCartTemplate.ejs",
"text!app/templates/footerTemplate.ejs",
"text!app/templates/getAllTemplate.ejs",
"text!app/templates/headerTemplate.ejs",
"text!app/templates/homeTemplate.ejs",
"text!app/templates/indexTemplate.ejs",
"text!app/templates/jobsTemplate.ejs",
"text!app/templates/loginTemplate.ejs",
"text!app/templates/overviewTemplate.ejs",
"text!app/templates/pictureTemplate.ejs",
"text!app/templates/portalTemplate.ejs",
"text!app/templates/registeredUsersTemplate.ejs",
"text!app/templates/userProfileTemplate.ejs"
],
function(){
return {
"templates/dashboardTemplate.ejs": arguments[0],
"templates/fluxCartTemplate.ejs": arguments[1],
"templates/footerTemplate.ejs": arguments[2],
"templates/getAllTemplate.ejs": arguments[3],
"templates/headerTemplate.ejs": arguments[4],
"templates/homeTemplate.ejs": arguments[5],
"templates/indexTemplate.ejs": arguments[6],
"templates/jobsTemplate.ejs": arguments[7],
"templates/loginTemplate.ejs": arguments[8],
"templates/overviewTemplate.ejs": arguments[9],
"templates/pictureTemplate.ejs": arguments[10],
"templates/portalTemplate.ejs": arguments[11],
"templates/registeredUsersTemplate.ejs": arguments[12],
"templates/userProfileTemplate.ejs": arguments[13]
}
});
然后您可以在前端需要模块,如下所示:
var footerView = require("app/js/jsx/standardViews/footerView");
但是,你可以看到这太冗长了,所以神奇的方式是这样的:
将上面的依赖项命名为allViews!
现在你可以这样做:
var allViews = require('allViews');
var footerView = allViews['standardViews/footerView'];
要求整个目录有两个好处:
(1)在生产中,使用r.js优化器,您可以指向一个依赖项(模块A),然后它可以轻松跟踪表示整个目录的所有A的依赖项
(2)在开发中,你可以预先要求整个目录,然后使用同步语法来要求依赖,因为你知道它们已经被加载了
享受“RequireJS-Metagen”
https://github.com/smartprocure/directory-metagen