Backbone Marionette和RequireJS Modules Confusion - 模块似乎未定义

时间:2013-09-13 10:29:56

标签: javascript backbone.js requirejs marionette

我刚开始使用Marionette,我正在Marionette - A Gentle Introduction阅读并跟随David Sulc。这是一个非常好的阅读,并且很容易跟随companion repository构建示例应用程序联系人管理器

但是,我之前使用RequireJS建立了一个项目,并希望将该书的想法和概念翻译并整合到该项目中。我实际上并没有那么远,我想我可能会对使用Marionette模块与AMD模块结合使用会产生undefined个对象感到有点困惑。

更具体地说,让我列出app.jslistView.jslistController.js,它们应该是此commit of the sample repo的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;
});

listView.js

/*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;
});

listController.js

/*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;
});

所以,我得到的错误是Uncaught TypeError: Cannot read property 'List' of undefined中的app.js:15引用了这一行:

ContactManager.ContactsApp.List.Controller.listContacts();

这意味着ContactsApp模块是undefined,这正是我不理解的。

据我了解,我将ContactsApp模块和List子模块附加到ContactManagerlistView.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();
});

1 个答案:

答案 0 :(得分:7)

RequireJS的基本工作方式如下:声明给定模块具有的所有依赖关系,然后在回调函数中使用它们。

以下是您的代码的问题:在app.js中,您只需要marionette,因此就RequireJS而言, nothing else应该为模块的代码加载功能齐全。但是,在同一个文件中,您调用ContactManager.ContactsApp.List.Controller.listContacts()。它来自哪里?无处:它没有在当前模块中定义,也没有被声明为依赖项。因此,它不存在,您会收到undefined问题。

您不能仅仅参考模块,认为它附加到主应用程序:它实际上只有在Marionette模块代码执行时才会附加。为此,需要将其作为依赖项。

顺便说一句,你将很难适应本书的代码与RequireJS一起使用,因为它不是为RequireJS使用而构建的(除了你遇到的问题,你还有循环依赖等等) )。

我建议你只是阅读这本书,以便自己对Marionette有一个良好的感觉,然后考虑将它与RequireJS一起使用。无耻的插件,我还写了book on marionette and requirejs