使用requirejs和backbonejs

时间:2015-05-21 10:47:50

标签: javascript object backbone.js requirejs globals

这是以易于理解的方式呈现,所以尽情阅读:)

我有一个骨干应用程序,它使用main.js文件初始化,如下所示:

require([
    'backbone',
    'app',
    'models/session'
], function (Backbone, Application, SessionModel) {


    //new Application();
    window.App = {
      session: new SessionModel()
    };

    new Application();

    Backbone.history.start();
});

如您所见,requirejs需要'app'作为第二个参数。

App只是一个看起来像这样的路由器(不太重要的部分已被删除)

define(function(require){
    'use strict';

    var Backbone = require('backbone'),
        Header = require('views/header'),
        Login = require('views/login');

    var Router = Backbone.Router.extend({

        initialize: function(){
            this.header = new Header();
            this.header.render();
        },


        routes: {
            'login': 'showLogin'
        },

        showLogin: function() {
            this.showView(new Login(), {requiresAuth: false});
            this.header.model.set('title', 'Login');
        },

        showView: function(view, options) {

            if(this.currentView) this.currentView.remove();
            $('.content').html(view.render().$el);
            this.currentView = view;

            return view;
        }

    });

    return Router;
});

这里重要的一点是,在第一行我需要

Header = require('views/header');

标题视图需要以标准方式显示另一个视图:

LogoutView = require('views/logout');

注销视图看起来像这样,在这里我找到了问题的本质:

define(function(require){
    'use strict';

    var Backbone = require('backbone'),
        JST = require('templates')

    return Backbone.View.extend({
        model: App.session,

        template: JST['app/scripts/templates/logout.hbs'],

        events: {
            'submit form': 'logout'
        },

        initialize: function(){
            this.listenTo(this.model, 'change', this.render)
        },

        render: function(){
            this.$el.html(this.template(this.model.toJSON()));

            return this;
        },

        logout: function(e){
            //nothing important here
        }

    });
});

正如你在Backbone.View.extend之后的第一行看到的那样,我正在尝试定义视图的模型属性:

model: App.session,

我认为应该可以访问,因为我正在定义:

window.App = {
      session: new SessionModel()
    };
<.>在main.js文件中。

但似乎存在一个需求问题,因为需要的是尝试获取程序第一行中的所有文件:

require([
    'backbone',
    'app', <<--- in this line it's trying to get all the files required in the app.js 
    'models/session'
], function (Backbone, Application, SessionModel) {

然后我收到了这个错误:

Uncaught ReferenceError: App is not defined   logout.js:8

这正是试图访问App全局变量的行:

 model: App.session,

这应该在运行main.js文件后定义,但它甚至没有那么远,因为需要获取文件并在LogoutView中找不到定义的App变量。

我可以通过在视图的初始化函数中定义模型来解决这个问题,如下所示:

initialize: function(){
    this.model = App.session;
    this.listenTo(this.model, 'change', this.render)
},

但我真正想要的是理解为什么会出现这种错误,以及使用Backbone.js和Require.js创建全局模型的最佳实践。

2 个答案:

答案 0 :(得分:1)

Eliom_registration.Html5define中的依赖项列表(require中的第一个参数或您在其他模块中使用的simplified wrapper)告诉RequireJS它应该在解释当前文件之前加载并解释这些模块。

以下是发生的事情:

  1. 第一个requirerequirebackboneapp作为依赖项
  2. 在评估其功能之前,它会加载其依赖项,然后查找它们的依赖项
  3. 冲洗并重复,直至到达models/session
  4. views/logout已解释,您尝试将views/logout分配给App.session,但此时不存在,并且您收到view.model错误
  5. 一种解决方案是创建App is not defined对象的单例,并在需要时对其进行处理。

    例如,假设您有Session

    globals/session

    您可以将应用定义为

    define(['models/session'], function (SessionModel) {
        return new SessionModel();
    });
    

    require([ 'backbone', 'app', 'globals/session' ], function (Backbone, Application, session) { //new Application(); window.App = { session: session }; new Application(); Backbone.history.start(); });

    中的相同更改
    view/logout

答案 1 :(得分:0)

在我发布此问题之前,以下代码或多或少是我尝试解决此问题的方法:

define(function(require) {
    'use strict';

    var SessionModel = require('models/session')

    var session = (function(){
        if(App.session instanceof SessionModel.constructor){
            return App.session;
        } else {
            App.session = new SessionModel()
            return App.session;
        }
    })();

    return session;
});

但我认为我已经因某种原因放弃了它,要么是因为App没有定义,要么似乎有更好的解决方案。

肮脏的黑客是我必须创建:

window.App = {};

就在我运行整个应用程序之前。