2013-02-04 17 views
6

commutazione ho la seguente situazione:Marionette layout strategia

app.js: Singleton Marionette.Application() dove definisco un navigatore, un piè, ed una regione principale. Nell'inizializzatore costruisco Marionette.Contoller e li allego sull'oggetto this.controller dell'app per un controllo successivo. Potrei non costruire tutti i Controller qui, solo quelli che desidero caricare. Alcuni sono Lazy Loaded più tardi. Ho anche un'istanza di un Backbone.Router qui, e passare un riferimento al mio oggetto app:

var theApp = new TP.Application(); 

theApp.addRegions(
{ 
    navRegion: "#navigation", 
    mainRegion: "#main", 
    footerRegoin: "#footer" 
}); 

theApp.addInitializer(function() 
{ 
    // Set up controllers container and eagerly load all the required Controllers. 
    this.controllers = {}; 

    this.controllers.navigationController = new NavigationController({ app: this }); 
    this.controllers.loginController = new LoginController({ app: this }); 
    this.controllers.calendarController = new CalendarController({ app: this }); 

    this.router = new Router({ app: this }); 
}); 

* * Controller.js: questo è un controller uso generale che gestisce vista & intsantiation modello e la gestione degli eventi. Ogni Controller possiede il proprio Marionette.Layout, da inserire nell'App.mainRegion. Ogni controller si collega all'evento "mostra" del layout per riempire le regioni del layout con visualizzazioni personalizzate. Ogni controller offre un'interfaccia getLayout() che restituisce il layout associato del controller.

Marionette.Controller.extend(
{ 
    getLayout: function() { return this.layout; }, 
    initialize: function() 
    { 
     this.views.myView = new MyView(); 
     ... 
     this.layout.on("show", this.show, this); 
     ... 
    }, 
    show: function() 
    { 
     this.layout.myViewRegion.show(myView); 
    } 
}); 

router.js: il router utilizza il singleton applicazione per caricare il layout di un controller nella zona principale della App:

... 
routes: 
{ 
    "home": "home", 
    "login": "login", 
    "calendar": "calendar", 
    "": "calendar" 
}, 
home: function() 
{ 
    var lazyloadedController = new LazyLoadController(); 
    this.theApp.mainRegion.show(lazyLoadController.getLayout()); 
}, 
login: function (origin) 
{ 
    this.theApp.mainRegion.show(this.theApp.controllers.loginController.layout); 
} 

Così com'è, tutto funziona bene, tranne per ricaricare lo stesso layout/controller due volte. Quello che succede è che gli eventi DOM definiti in LoginView non si re-legano sul secondo show. Che è facilmente risolto spostando il codice di inizializzazione LoginView nel gestore di eventi "show" per il controller:

LoginController = Marionette.Controller.extend(
{ 
    ... 
    show: function() 
    { 
     if (this.views.loginView) 
      delete this.views.loginView.close(); 

     this.views.loginView = new LoginView({ model: this.theApp.session }); 
     this.views.loginView.on("login:success", function() 
     { 
     }); 

     this.layout.mainRegion.show(this.views.loginView); 
    } 

Ora tutto funziona bene, ma annulla parte del motivo che ho creato di cominciare con il controller: li voglio per possedere una vista e i suoi modelli, crearli una volta e non dover distruggere & ricrearli ogni volta che cambio layout.

Mi manca qualcosa? Non è così che dovrei usare Layouts? Non è l'intero punto di Layouts e Regioni che posso passare a Viste & a piacere?

Ovviamente non vorrei tornare indietro a LoginController/Layout spesso, ma che dire tra un HomeController/Layout, CalendarController/Layout, SummaryController/Layout, ecc ... in un'applicazione a singola pagina potrei passare da quelli in alto -levelo di layout piuttosto spesso e vorrei che la vista restasse nascosta in background.

risposta

7

Penso che il problema è che non si mantiene una singola istanza del controller. Il metodo consigliato per gestire di routing/regolatori (sulla base di Brian Mann's videos) è come questo

App.module('Routes', function (Routes, App, Backbone, Marionette, $, _) { 

    // straight out of the book... 
    var Router = Marionette.AppRouter.extend({ 
     appRoutes: { 
      "home": "home", 
      "login": "login", 
      "calendar": "calendar" 
     } 
    }); 

    var API = { 
     home: function() { 
      App.Controller.go_home(); 
     }, 
     login: function() { 
      App.Controller.go_login(); 
     }, 
     calendar: function() { 
      App.Controller.go_calendar(); 
     } 
    }; 

    App.addInitializer(function (options) { 
     var router = new Router({controller: API}); 
    }); 
}); 

... e il controller:

App.module("Controller", function (Controller, App, Backbone, Marionette, $, _) { 
    App.Controller = { 
     go_home: function() { 
      var layout = new App.Views.Main(); 
      layout.on('show', function() { 
       // attach views to subregions here... 
       var news = new App.Views.News(); 
       layout.newsRegion.show(news); 
      }); 

      App.mainRegion.show(layout); 
     }, 

     go_login: function() { 
      .... 
     }, 

     go_calendar: function() { 
      .... 
     } 
    }; 
}); 

ho sospetto il tuo problema è il controller pigro-caricato. ..

Problemi correlati