2015-05-21 4 views
3

Это представлено в легко понять моду, так что наслаждайтесь чтением :)Создания/Доступ к глобальному объекту с requirejs и backbonejs

У меня есть магистральное приложение, которое инициализируется с 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 только маршрутизатор, который выглядит примерно так (менее важными деталями были удален)

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, но оно даже не заходит так далеко, как требует получение файлов и находит не определенную переменную App в LogoutView.

я могу обойти эту проблему, определив модель внутри функции инициализации в представлении, как так:

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

Но что я действительно хочу, чтобы понять, почему происходит эта ошибка, и что является лучшей практикой создания глобальных моделей с использованием Backbone.js и Require.js.

ответ

1

Список зависимостей в define или require (первый аргумент в вашей require или simplified wrapper вы используете в своих других модулей) говорит RequireJS, что он должен загрузить и интерпретировать те модули перед интерпретацией текущего файла.

Вот что происходит:

  1. Первый require имеет backbone, app, models/session в качестве зависимостей
  2. до его функции вычисляются, он загружает его зависимость и, в свою очередь ищет их зависимости
  3. Полоскания и повторите, пока не достигнете views/logout
  4. views/logout интерпретируется, вы пытаетесь присвоить App.sessionно не существует в этой точке, и вы получите 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

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

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

    return Backbone.View.extend({ 
     model: require('globals/session'), 
     ... 
    }); 
}); 
+0

Да, спасибо за ответ, я знал, что происходит, но спасибо за очки, это поможет другим с проблемой точно. Итак, вы говорите, что нет возможности иметь глобальную переменную за пределами области requirejs, и вам нужно ее присоединить к ней? – matewilk

+0

У вас могут быть глобальные переменные, вам просто нужно знать порядок, в котором эти файлы включены. Я предпочитаю иметь модуль, посвященный этим переменным, которые я могу включить по своему усмотрению, и это не загрязняет глобальную область. – nikoshr

+0

Да, я имел в виду наличие переменных в глобальной области, не загрязняя их, что немного противоречиво. Но да, вы правы, лучше не загрязнять глобальную сферу. Спасибо, что освободили! О да, и еще одна вещь, это синглтон, который вы показали в первом фрагменте кода? Похоже, он возвращает новый SessionModel (NEW) каждый раз, когда вы его требуете. Или это какая-то магия requirejs? – matewilk

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

Но я думаю, что я отказался от него по какой-то причине, либо потому, что приложение не было определено или, может быть, казалось, что это лучшее решение для этого.

Грязный хак было то, что я должен был создать:

window.App = {}; 

Просто, прежде чем я бегала все приложение.

Смежные вопросы