Javascript 主干木偶和RequireJS模块混淆–;模块似乎未定义
我刚开始使用木偶,我正在阅读并跟随。这是一本非常好的读物,并且很容易使用构建示例应用程序联系人管理器 然而,我之前使用RequireJS建立了一个项目,并希望将该书的思想和概念翻译并集成到这个项目中。实际上我还没有做到这一点,我想我可能对木偶模块与AMD模块的结合使用有点困惑,这会导致Javascript 主干木偶和RequireJS模块混淆–;模块似乎未定义,javascript,backbone.js,requirejs,marionette,Javascript,Backbone.js,Requirejs,Marionette,我刚开始使用木偶,我正在阅读并跟随。这是一本非常好的读物,并且很容易使用构建示例应用程序联系人管理器 然而,我之前使用RequireJS建立了一个项目,并希望将该书的思想和概念翻译并集成到这个项目中。实际上我还没有做到这一点,我想我可能对木偶模块与AMD模块的结合使用有点困惑,这会导致未定义的对象 更具体地说,让我列出app.js、listView.js和listController.js,它们应该是此应用程序的RequireJS版本 app.js /*global define*/ defin
未定义的对象
更具体地说,让我列出app.js
、listView.js
和listController.js
,它们应该是此应用程序的RequireJS版本
app.js
/*global define*/
define([
'marionette'
], function ( Marionette ) {
'use strict';
var ContactManager = new Marionette.Application();
ContactManager.addRegions({
mainRegion : '#main-region'
});
ContactManager.on( 'initialize:after', function() {
ContactManager.ContactsApp.List.Controller.listContacts();
});
return ContactManager;
});
/*global define*/
define([
'app',
'marionette',
'handlebars',
'text!templates/contact.hbs'
], function ( ContactManager, Marionette, Handlebars, contactTemplate ) {
'use strict';
var List = ContactManager.module( 'ContactsApp.List' );
List.Contact = Marionette.ItemView.extend({
tagName: 'li',
template : Handlebars.compile( contactTemplate ),
});
List.Contacts = Marionette.CollectionView.extend({
tagName: 'ul',
itemView: List.Contact
});
return List;
});
/*global define*/
define([
'app'
], function ( ContactManager ) {
'use strict';
var List = ContactManager.module( 'ContactsApp.List');
List.Controller = {
listContacts: function() {
var contacts = ContactManager.request('contact:entities');
var contactsListView = new ContactManager.ContactsApp.List.Contacts({
collection: contacts
});
ContactManager.mainRegion.show( contactsListView );
}
};
return List.Controller;
});
listView.js
/*global define*/
define([
'marionette'
], function ( Marionette ) {
'use strict';
var ContactManager = new Marionette.Application();
ContactManager.addRegions({
mainRegion : '#main-region'
});
ContactManager.on( 'initialize:after', function() {
ContactManager.ContactsApp.List.Controller.listContacts();
});
return ContactManager;
});
/*global define*/
define([
'app',
'marionette',
'handlebars',
'text!templates/contact.hbs'
], function ( ContactManager, Marionette, Handlebars, contactTemplate ) {
'use strict';
var List = ContactManager.module( 'ContactsApp.List' );
List.Contact = Marionette.ItemView.extend({
tagName: 'li',
template : Handlebars.compile( contactTemplate ),
});
List.Contacts = Marionette.CollectionView.extend({
tagName: 'ul',
itemView: List.Contact
});
return List;
});
/*global define*/
define([
'app'
], function ( ContactManager ) {
'use strict';
var List = ContactManager.module( 'ContactsApp.List');
List.Controller = {
listContacts: function() {
var contacts = ContactManager.request('contact:entities');
var contactsListView = new ContactManager.ContactsApp.List.Contacts({
collection: contacts
});
ContactManager.mainRegion.show( contactsListView );
}
};
return List.Controller;
});
listController.js
/*global define*/
define([
'marionette'
], function ( Marionette ) {
'use strict';
var ContactManager = new Marionette.Application();
ContactManager.addRegions({
mainRegion : '#main-region'
});
ContactManager.on( 'initialize:after', function() {
ContactManager.ContactsApp.List.Controller.listContacts();
});
return ContactManager;
});
/*global define*/
define([
'app',
'marionette',
'handlebars',
'text!templates/contact.hbs'
], function ( ContactManager, Marionette, Handlebars, contactTemplate ) {
'use strict';
var List = ContactManager.module( 'ContactsApp.List' );
List.Contact = Marionette.ItemView.extend({
tagName: 'li',
template : Handlebars.compile( contactTemplate ),
});
List.Contacts = Marionette.CollectionView.extend({
tagName: 'ul',
itemView: List.Contact
});
return List;
});
/*global define*/
define([
'app'
], function ( ContactManager ) {
'use strict';
var List = ContactManager.module( 'ContactsApp.List');
List.Controller = {
listContacts: function() {
var contacts = ContactManager.request('contact:entities');
var contactsListView = new ContactManager.ContactsApp.List.Contacts({
collection: contacts
});
ContactManager.mainRegion.show( contactsListView );
}
};
return List.Controller;
});
因此,我得到的错误是未捕获类型错误:无法读取app.js:15
中未定义的属性“List”:
ContactManager.ContactsApp.List.Controller.listContacts()代码>
这意味着ContactsApp
模块是未定义的
,这正是我不理解的
据我所知,我将ContactsApp
模块和List
子模块连接到ContactManager
中的listView.js
或listController.js
(以先调用的为准)中,并带有以下行:
ContactManager.module('ContactsApp.List')代码>
那么,ContactsApp
不应该在app.js
中定义吗
这是main.js文件,其中包括require.config
和应用程序的入口点:
require.config({
baseUrl: './scripts',
paths: {
jquery : '../bower_components/jquery/jquery',
underscore : '../bower_components/underscore/underscore',
backbone : '../bower_components/backbone/backbone',
marionette : '../bower_components/backbone.marionette/lib/backbone.marionette',
bootstrap : '../bower_components/sass-bootstrap/dist/js/bootstrap',
text : '../bower_components/requirejs-text/text',
handlebars : '../bower_components/handlebars/handlebars',
templates : '../templates'
},
shim: {
underscore : {
exports : '_'
},
backbone : {
deps : [ 'underscore', 'jquery' ],
exports : 'Backbone'
},
marionette : {
deps : [ 'backbone' ],
exports : 'Backbone.Marionette'
},
bootstrap : {
deps : [ 'jquery' ],
},
handlebars : {
exports : 'Handlebars'
}
},
deps : [ 'jquery', 'underscore' ]
});
require([
'app',
'bootstrap'
], function ( ContactManager ) {
'use strict';
ContactManager.start();
});
RequireJS基本上是这样工作的:声明给定模块的所有依赖项,然后在回调函数中使用它们
您的代码有一个问题:在app.js
中,您只需要木偶
,因此就RequireJS而言,不应加载任何其他内容,模块的代码才能正常工作。但是,在同一个文件中,调用ContactManager.ContactsApp.List.Controller.listContacts()
。那是从哪里来的?无处:它未在当前模块中定义,也未声明为依赖项。因此,它不存在,您会遇到未定义的问题
您不能仅仅引用模块,认为它已附加到主应用程序:它实际上只有在执行木偶模块代码时才会附加。要实现这一点,需要将其作为依赖项
顺便说一句,您将很难将本书的代码调整为与RequireJS一起使用,因为它不是为RequireJS的使用而设计的(除了您遇到的问题之外,您还将有循环依赖关系,等等)
我建议你阅读这本书,对木偶本身有一个很好的感觉,然后研究如何在RequireJS中使用它。无耻的插件,我还写了一封。谢谢你的快速回复,大卫。我认为不在app.js
中包含控制器应该是可以的,因为我正在将控制器子模块连接到ContactManager
中的listController.js
。我假设控制器可以在app.js
中的ContactManager
上使用。似乎不是这样的?!如果我在app.js
中的define块中包含listController
,我将再次遇到循环依赖。那么,这将是一个好的、干净的方法吗?另外,我知道你的另一本书,我也在阅读源代码,但因为我还不是很熟悉木偶,所以在这一点上,不是所有的东西都对我有意义。我想我会听从你的建议,自己完成这本书,并希望带有requirejs和木偶回购的结构化主干对我来说会更有意义。是否从和“翻译”完成的联系人管理器应用程序开始在这本书中,它将与RequireJS一起使用,还是您从头开始启动应用程序?我编辑了我的答案,以澄清为什么连接到主应用程序的模块并不意味着您可以立即使用它。第二本书从完成的应用程序开始,向您展示如何“转换”它以使用RequireJS。它还涵盖了一些其他的主题(例如,混合木偶和RequireJS模块,根据路由路径启动/停止模块)