【问题标题】:Backbone Marionette and RequireJS Modules Confusion – module seems to be undefinedBackbone Marionette 和 RequireJS 模块混淆 - 模块似乎未定义
【发布时间】:2013-09-13 10:29:55
【问题描述】:

我刚开始使用 Marionette,我正在阅读并关注 Marionette - A Gentle IntroductionDavid Sulc。这是一本非常好的读物,并且很容易通过companion repository 构建示例应用程序Contact Manager

但是,我之前使用 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 in app.js:15 指的是这一行:

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

这意味着ContactsApp模块是undefined,这正是我不明白的。

据我了解,我将ContactsApp 模块和List 子模块附加到ContactManager 内的listView.jslistController.js(以先调用者为准)与以下行:

ContactManager.module( 'ContactsApp.List' );

那么ContactsApp不应该在app.js中定义吗?

这是 ma​​in.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();
});

【问题讨论】:

    标签: javascript backbone.js requirejs marionette


    【解决方案1】:

    RequireJS 基本上是这样工作的:声明给定模块的所有依赖项,然后在回调函数中使用它们。

    这是您的代码的问题:在 app.js 中,您只需要 marionette 就 RequireJS 而言,什么都没有应该加载其他模块的代码才能正常工作。但是,在同一个文件中,您调用ContactManager.ContactsApp.List.Controller.listContacts()。那是从哪里来的?无处:它没有在当前模块中定义,也没有声明为依赖项。因此,它不存在,您会收到 undefined 问题。

    您不能只引用模块,认为它附加到主应用程序:它只有在执行 Marionette 模块代码时才真正附加。为此,需要将其作为依赖项。

    顺便说一句,您将很难调整本书的代码以与 RequireJS 一起使用,因为它不是为 RequireJS 使用而设计的(除了您遇到的问题之外,您还会有循环依赖等.).

    我建议您直接阅读本书,以便单独了解 Marionette,然后考虑将其与 RequireJS 一起使用。无耻的外挂,我还写了book on marionette and requirejs

    【讨论】:

    • 感谢您的快速回复,大卫。我认为不将控制器包含在app.js 中应该没问题,因为我将控制器子模块附加到listController.js 内部的ContactManager。我假设控制器将在app.js 中的ContactManager 上可用。好像不是这样的?!如果我在app.js 的定义块中包含listController,我将再次遇到循环依赖。那会是一个好的和干净的方法吗?
    • 另外,我知道你的另一本书,我也在阅读源代码,但由于我对 Marionette 还不是很熟悉,所以目前对我来说并不是所有的东西都有意义。我想我会听从你的建议,自己完成这本书,并希望 structuring-backbone-with-requirejs-and-marionette repo 对我来说更有意义。
    • Structuring Backbone Code with RequireJS and Marionette Modules 是从 Backbone.Marionette.js: A Gentle Introduction 完成的联系人管理器应用程序开始并“翻译”它以与 RequireJS 一起使用,还是在本书中从头开始应用程序?
    • 我已经编辑了我的答案,以澄清为什么附加到主应用程序的模块并不意味着您可以立即使用它。第二本书从完成的应用程序开始,向您展示如何“转换”它以使用 RequireJS。它还涵盖了一些其他主题(例如混合 Marionette 和 RequireJS 模块,根据路由路径启动/停止模块)
    猜你喜欢
    • 2012-07-07
    • 2014-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 2016-02-28
    • 1970-01-01
    相关资源
    最近更新 更多