Javascript 如何在使用AMD(require.js)时在Backbone.js中加载引导模型
Backbone.js文档建议通过以下方式加载引导模型:Javascript 如何在使用AMD(require.js)时在Backbone.js中加载引导模型,javascript,backbone.js,requirejs,js-amd,Javascript,Backbone.js,Requirejs,Js Amd,Backbone.js文档建议通过以下方式加载引导模型: <script> var Accounts = new Backbone.Collection; Accounts.reset(<%= @accounts.to_json %>); var Projects = new Backbone.Collection; Projects.reset(<%= @projects.to_json(:collaborators => true) %>); <
<script>
var Accounts = new Backbone.Collection;
Accounts.reset(<%= @accounts.to_json %>);
var Projects = new Backbone.Collection;
Projects.reset(<%= @projects.to_json(:collaborators => true) %>);
</script>
var账户=新主干。集合;
Accounts.reset();
var Projects=新主干网集合;
项目。重置(正确)%>);
但这是一种不能在AMD方法中使用的模式(使用require.js)
唯一可能的解决方案是声明存储JSON数据的全局变量,然后在相关的初始化方法中使用该变量
有没有更好的方法来做这件事(没有globals)?这样做怎么样:
<script>
define('Models', ['backbone'], function(Backbone) {
var Models = {
Accounts: new Backbone.Collection,
Projects: new Backbone.Collection
};
Models.Accounts.reset(<%= @accounts.to_json %>);
Models.Projects.reset(<%= @projects.to_json(:collaborators => true) %>);
return Models;
});
</script>
var models = require(['Models']);
models.Accounts.doWhatYouNeed();
或者这个:
define(['any', 'dependencies', 'and', 'Models'], function(a, b, c, Models) {
// Models will be available here
});
您可以在AMD模块的末尾添加一个循环函数,以检查何时定义了init方法(以便可以在body之后填充它,或者从include加载它)。这样可以保证模块可用,并且在准备就绪时可以进行初始化
require(...,function (...) {
//define models collections, etc..
var initme = function () {
if(document.initThisModule)
document.initThisModule();
else
setTimeout(initme, 10);
}();
});
我对AMD方法不太熟悉,但与其使用全局变量,不如将JSON添加到dom中
例如:
var json = ...,
$jsonContainer = $(json).wrap("<script id='json-container' type='text/javascript'>").appendTo($("body"));
这就是我们引导数据的方式,它不会污染全局名称空间。相反,它专门使用require.js。它还帮助您根据模板中的变量提供初始应用程序配置 在呈现的页面中
定义('config',函数(){
返回{
引导帐户:,
bootstrappedProjects:true)%%>
};
});
globals.js
此文件检查配置并使用返回的任何数据扩展自身
定义([
“配置”,
“下划线”
],函数(配置){
变量全局={
};
_.extend(全局,配置);
返回全局;
});
config.js
无论您是否在页面中定义了config
,如果您希望能够加载应用程序,则需要此文件
define(函数(){
//页面中未定义“config”的情况的空数组
返回{};
});
app.js
需要([
“全球”,
“下划线”,
“骨干”
],函数(全局){
if(全局引导帐户){
var accounts=新主干.Collection(globals.bootstrappedAccounts);
}
if(globals.bootstrappedProjects){
var projects=new Backbone.Collection(globals.bootstrappedProjects);
}
});
看起来您可以使用require.config()函数或带有“config”选项的“require”全局函数,以便通过特殊依赖项“module”将数据传递给模块。见:
通常需要将配置信息传递给模块。那个
配置信息通常是应用程序的一部分,并且
需要有一种方法将其传递给模块。在《还魂曲》中,
这是通过requirejs.config()的config选项完成的。模块
然后可以通过请求特殊依赖项“模块”来读取该信息
并调用module.config()
因此,对于引导模型,在顶级HTML页面中:
<script>
var require = {
config: {
'app': {
bootstrappedAccounts: <%= @accounts.to_json %>
bootstrappedProjects: <%= @projects.to_json(:collaborators => true) %>
}
}
};
</script>
<script src="scripts/require.js"></script>
这里的“模块”是为这些类型的案例提供的特殊依赖项
这是未经测试的,但从文档中看起来非常确定。这里的一些答案让我接近我的类似问题,但没有解决它。特别是排名靠前且被接受的答案似乎给了我一个恶劣的比赛条件,有时虚拟对象会先加载。当与Optimizer一起使用时,这种情况也会100%发生。它还为模块使用显式字符串名称,require文档特别建议您不要这样做 我是这样做的。与Brave Dave类似,我使用config对象捕获参数(在我的例子中是从jsp页面),如下所示 关键的一点是,config对象上必须有一个键mod.map.id解析为“options”的属性 从这里,您现在可以像这样访问模型
define(['module'], function(module){
console.log(module.config().bootstrappedModels);
//...
});
正如上面所描述的,“数据模块”(或配置,或任何你想叫它的东西)可以包含在已经生成的文件中(例如index.html),但我认为这相当难看 另一种方法是在其自己的模块文件中声明它,但这需要在生产环境中额外往返到服务器。只要您想要构建和优化您的requirejs依赖项,就不能包含数据模块,因为它是在页面加载时动态生成的
第三个选项可能是将其附加到您提供的一个文件(例如,优化的requirejs文件)中,但我不知道如何/是否可以这样做。在requirejs中,这是通过
requirejs.config()的配置选项完成的。
。然后,模块可以通过请求特殊依赖项“module”并调用module.config()
来读取该信息。例如:
index.html
<script>
var require = {
config: {
'app': {
'api_key': '0123456789-abc'
}
}
};
</script>
<script src="js/libs/require.js" data-main="js/main"></script>
app.js
require( ['app'], function(App) {
new App();
});
define( ['module'], function(module) {
var App = function() {
console.log( 'API Key:', module.config().api_key );
};
return App;
});
请注意,配置对象的名称必须与模块的名称匹配。在我的示例中,模块的名称是app
,因此配置对象的名称也需要命名为app
。在模块中,您需要将['module']
作为依赖项,并调用module.config()[property name]
来检索配置数据
阅读有关此的文档:Ansewr by@dlrust-work,但它无法扩展参数并从代码中的一个位置传递多个参数。如果尝试在渲染模板中执行以下操作:
<script>
define('config', function() {
return {
bootstrappedAccounts: <%= @accounts.to_json %>,
bootstrappedProjects: <%= @projects.to_json(:collaborators => true) %>
};
});
</script>
global.js
index.php
index.js
文件结构:
意识到这不是一个答案,移动到评论:我使用require.js和bootstrap。我基本上做了你不想做的事。第一个获取的页面具有我引导的JSON数据的全局变量。我复制/使用这些值填充初始模型和集合。我不确定这是不是一种不好的方式。如果你担心会污染全局空间,你不能先删除这些变量吗
<script>
var require = {
config: {
'app': {
'api_key': '0123456789-abc'
}
}
};
</script>
<script src="js/libs/require.js" data-main="js/main"></script>
require( ['app'], function(App) {
new App();
});
define( ['module'], function(module) {
var App = function() {
console.log( 'API Key:', module.config().api_key );
};
return App;
});
<script>
define('config', function() {
return {
bootstrappedAccounts: <%= @accounts.to_json %>,
bootstrappedProjects: <%= @projects.to_json(:collaborators => true) %>
};
});
</script>
<script>
define('config', function() {
return {
goods: <%= some data %>,
showcaseList: <%= some json or array %>
};
});
</script>
define("App", [], function() {
window.App = {
// модели
Model: {},
// коллекции
Collection: {},
// виды
View: {},
// роутеры
Router: {},
// модальные окна
Modal: {},
// UI компоненты
UI: {}
};
return window.App;
});
define(["App", "underscore", "backbone"], function(App, _, Backbone) {
"use strict";
// модель глобальных данных
App.Model.Global = Backbone.Model.extend({
defaults: {}
});
return new App.Model.Global;
});
<!DOCTYPE html>
<html>
<head>
<!--HEAD_START-->
<script type="text/javascript" data-main="/app/init" src="/app/require/require.js"></script>
<!--HEAD_END-->
</head>
<body>
<div id="tm-inner-wrap">
<div id="loader"><i class="uk-icon-refresh uk-icon-spin"></i></div>
<!--HEADER_START-->
<?= $this->includeTpl('header_view'); ?>
<!--HEADER_END-->
<!--CONTENT_START-->
<div>your html content data</div>
<!--CONTENT_END-->
<!--FOOTER_START-->
<?= $this->includeTpl('footer_view');?>
<!--FOOTER_END-->
<script>
require(["global"], function(Global) {
Global.set("notifyList", <?=json_encode($this->notifyList);?>);
});
</script>
</div>
</body>
</html>
<div class="tm-inner-body">
<div class="uk-container uk-container-center">
// content data
</div>
</div>
<script>
require(["global", "module/index"], function(Global) {
Global.set("goodList", <?=json_encode($this->goodList);?>);
});
</script>
require(["App", "core", "jquery", "uikit!uikit-addons-min", "underscore", "backbone", "global", "module/good/goodView"], function(App, Core, $, UIkit, _, Backbone, Global, goodView) {
"use strict";
// Global.get("notifyList"); its too able
App.Collection.Good = new Backbone.Collection(Global.get("showcaseList")["items"]);
// вид списка товаров
App.View.GoodList = Backbone.View.extend({
// елемент
el: ".tm-good-list",
// init
initialize: function() {
this.collection = App.Collection.Good;
// список товаров
this.drawList();
},
// отрисовка списка
drawList: function() {
this.$el.empty();
this.collection.each(function(item, index) {
this.$el.append(this.drawItem(item));
}, this);
},
// отрисовка елемента
drawItem: function(data) {
var good = new goodView({model: data});
return good.render().el;
}
});
App.View.Index = Backbone.View.extend({
el: "body",
// пользовательские события
events: {
//
},
// init
initialize: function() {
var $this = this;
if(Global.get("showcaseList")) new App.View.GoodList();
}
});
new App.View.Index();
});