您好我正在尝试以动态方式加载一些requireJs模块,方法是获取一个过滤器列表和迭代数组以加载这样的模块
define(function(require){
var runFilters = function(filters){
var _ = require('underscore');
var computedFilters = getFilters(filters);
var result = _.every(computedFilters,function(filter){
return filter();
});
return result;
};
var getFilters = function(filters){
var _ = require('underscore');
return _.map(filters,function(filter){
return require('filters/' + filter);
},this);
}
var register = function(filters,fn){
return function(){
var args = Array.prototype.slice.apply(arguments);
if(runFilters(filters))
fn.apply(this,args);
}
}
return{
register: register
}
});
这给我发错:未捕获错误:模块名称“filters / isAuth”尚未加载上下文:_
但是当将其替换为静态方式(仅用于测试)时,它会完全加载
define(function(require){
var runFilters = function(computedFilters){
var result = _.every(computedFilters,function(filter){
return filter();
});
return result;
};
var getFilters = function(filters){
var _ = require('underscore');
return _.map(filters,function(filter){
console.log(filter);
return require('filters/' + filter);
},this);
}
var register = function(filters,fn){
var cachedFilters = [];
cachedFilters.push(require('filters/isAuth'));
return function(){
var args = Array.prototype.slice.apply(arguments);
if(runFilters(cachedFilters))
fn.apply(this,args);
}
}
return{
register: register
}
});
这也给我错误
cachedFilters.push(require('filters'+'/isAdmin'));
答案 0 :(得分:7)
你遇到了RequireJS对CommonJS语法支持的限制。这是交易。当RequireJS定义模块时,它会查看您为define
提供的工厂函数(回调)。它寻找这种模式:
/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g
这匹配require
调用,如var foo = require('foo');
。对于每个此类调用,它会将所需模块添加到模块的依赖项列表中。因此,例如:
// The `require` parameter must be present and is filled with something useful
// by RequireJS.
define(function (require) {
var foo = require('foo');
var bar = require('bar');
...
});
这样对待:
define(['require', 'foo', 'bar'], function (require) {
var foo = require('foo');
var bar = require('bar');
...
});
如果仔细查看上面的正则表达式,您会发现它只会匹配{em>单参数的require
次调用,该参数是文字字符串。因此require("something" + somevar)
之类的东西不起作用。在进行此转换时,RequireJS完全忽略它们。
通过更改正则表达式无法修复此问题。 RequireJS的核心是一个用于异步加载模块的系统。使用单个字符串文字的require
调用的形式是糖,以允许更容易移植根据CommonJS模式设计的模块,以及喜欢这种风格的人(即使他们没有移植任何东西)。这种类型的调用看起来是同步的,而实际上不是同步为了支持计算传递给它的名称的情况,RequireJS必须预测该值是什么。
如果您希望完全自由地在代码中加载所需的任何模块,而不事先知道名称是什么,那么您必须使用异步require
调用(require([computed_value], function(mod) {...})
)这意味着您的代码必须是异步的。如果你想要加载一组有限的模块,并且总是可以加载所有模块,那么你可以用文字字符串来要求它们全部:
define(function (require) {
require("filters/isAdmin");
require("filters/b");
require("filters/c");
require("filters/d");
...
});
RequireJS将进行上述转换,并且使用解析为模块中早期所需名称之一的计算值的require
调用不会失败。