RequireJS 通过定义所有模块的依赖关系来工作。由于main.js 在执行任何其他操作之前需要app,因此它将首先加载app 依赖的所有文件。由于app 需要router,router 需要ProjectListView,而ProjectListView 需要其基于文本的模板,因此这些文件都会在在任何事情发生之前加载; RequireJS 首先确保define(...) 或require(...) 函数中的每个回调都有它需要的内容。这正如预期的那样。
如果您想将文件的加载推迟到实际创建视图之前,您可以以不同的方式构建视图。它使事情变得相当复杂,这就是为什么大多数人不这样做。
以下是示例应用程序中使用ProjectListView 的一个选项。它使用When JS 提供一个Promise 来处理模板的异步加载。这也有使render 函数异步的不幸副作用,因为它可能需要等待模板文件出现。还是……
define([
'jquery',
'underscore',
'backbone',
'when'
], function($, _, Backbone, when){
var ProjectListView = Backbone.View.extend({
el: $('#container'),
initialize: function() {
// Load the template file upon the creation of the view
this._ensureTemplateLoaded();
},
// This returns a Promise that will be resolved after the
// template file is loaded.
_ensureTemplateLoaded: function() {
var self = this;
return when.promise(function(resolve) {
// Require in the template. Note that this is
// a no-op if the template has been loaded previously
require([
'text!templates/project/list.html'
], function(projectListTemplate) {
// Resolve our promise, providing the template
resolve(projectListTemplate);
});
});
},
render: function(){
// Wait for the promise to be resolved to make sure
// we have loaded the template before attempting to render
var self = this;
this._ensureTemplateLoaded().then(function(projectListTemplate) {
// Huzzah! Now we can do the regular rendering with the
// template provided by the Promise
var data = {};
var compiledTemplate = _.template( projectListTemplate, data );
// Append our compiled template to this Views "el"
self.$el.append( compiledTemplate );
});
}
});
// Our module now returns our view
return ProjectListView;
});
如前所述,它有点复杂。除非您要加载大量文件,否则对最终用户的好处微乎其微。
最后,请注意 RequireJS 的优化器 r.js 可以通过构建多个完全组装的 JS 模块(即目标模块及其所有依赖项)来有效地完成相同的事情。然而,这通常意味着客户端会多次下载同一个 JS,因此它也仅用于分离大型应用程序的不同组件。
http://requirejs.org/docs/optimization.html.