Backbone.js 如何布局复杂的应用程序及其视图/区域/布局

Backbone.js 如何布局复杂的应用程序及其视图/区域/布局,backbone.js,marionette,Backbone.js,Marionette,即使在阅读了一些关于如何构建主干木偶应用程序的教程和博客文章后,我还是在编写自己的应用程序时感到困惑。这是我的设置 我有一个应用程序,可以很容易地构造成不同的子应用程序(又名主干模块) 单击我的主导航栏中的链接可启动其中一个应用程序。这意味着它会将应用程序启动布局加载到我的主分区中 但这些应用程序本身具有不同的布局,因此在应用程序内部导航会覆盖主应用程序布局中指定的区域 e、 g 其中layout具有以下DOM树,每个DOM树映射到一个区域 #app_main .albums .arti

即使在阅读了一些关于如何构建主干木偶应用程序的教程和博客文章后,我还是在编写自己的应用程序时感到困惑。这是我的设置

我有一个应用程序,可以很容易地构造成不同的子应用程序(又名主干模块) 单击我的主导航栏中的链接可启动其中一个应用程序。这意味着它会将应用程序启动布局加载到我的主分区中

但这些应用程序本身具有不同的布局,因此在应用程序内部导航会覆盖主应用程序布局中指定的区域

e、 g

其中layout具有以下DOM树,每个DOM树映射到一个区域

#app_main
  .albums
  .artists
然后我做一些类似的事情

layout.app_main.show(new myView())
从现在起,即使使用back按钮(使用主干路由器和History),我也无法访问layout.albums或layout.artists


我是否应该将模块的主布局拆分为仅包含#app#u main,并在单独的步骤中将开头布局加载到其中?或者您还有其他想法吗?

在我自己的项目中,作为一般规则,我总是将定义区域的元素保留为空,然后在
Layout.onRender
方法中动态加载它们。这在Marionette.Async中还有一个额外的好处,即如果我需要在区域中显示视图之前从服务器加载额外的数据,我可以在视图的
beforeRender
方法中这样做


我的规则的一个例外是在区域的元素中显示一个动画的“loading…”div,它在填充区域时会被覆盖。

了解更多关于您要做的事情会有所帮助,但这里有一个答案。如果有帮助,请告诉我

假设这是您的HTML布局:

<div id="app">
  <div id="app_nav">
    <a href="#music">Music</a>
    <a href="#books">Books</a>
  </div>
  <div id="sub_app"></div>
</div> <!-- /#app_main -->
--

现在来建立我们的木偶视图

在myApp.js中

var myApp = new Backbone.Marionnette.Application();

myApp.addRegions({
  subAppRegion: "#sub_app"
});

// Your data
myApp.artists = new Backbone.Collection([...]);
myApp.books = new Backbone.Collection([...]);
在myApp.musicApp.js中

myApp.module("musicApp", function(musicApp, myApp) {
  /* Setup your Views
   ================== */
  var MusicLayout = Backbone.Marionette.Layout.extend({
    template: #musicApp-template",
    regions: {
      albumsRegion: ".albums",
      artistsRegion: ".artists"
    }
  });

  var AlbumView = Backbone.Marionette.ItemView.extend({
    template: "#album-template"
  });

  var AlbumListView = Backbone.Marionette.CollectionView({
    itemView: AlbumView
  });

  var ArtistView = ...
  var ArtistListView = ...

  /* Create router for app navigation
   ==================================== */
  var Router = Backbone.Marionette.AppRouter.extend({
    appRoutes: {
      "music" : showMusicApp
    },
    controller: musicApp
  });
  new Router();

  /* Method to show the music app
   ================== */
  musicApp.showMusicApp = function() {
    // Instantiate Views
    var musicLayout = new MusicLayout();
    var albumListView = new AlbumListView({ collection: myApp.albums });
    var artistListView = new ArtistsListView({ collection: myApp.artists });

    // Show musicApp layout in subAppRegion of main app
    myApp.subAppRegion.show(musicLayout);

    // Show albums and artists in musicApp layout
    layout.albumsRegion.show(albumListView);
    layout.artistsRegion.show(artistListView);
  }
});
您可以使用大致相同的方法设置
myApp.booksApp
模块:

myApp.module("booksApp", function(booksApp, myApp) {
  ...
  var Router = Backbone.Marionette.AppRouter.extend({
    appRoutes: {
      "books" : showBooksApp
    },
    controller: booksApp
  });
  new Router();

  booksApp.showBooksApp = function() {
    ...
    myApp.subAppRegion.show(booksLayout)
    ...
  }
  ...
});
我还没有测试所有这些代码,所以如果有一些问题,我很抱歉,我相信它可以改进


如果你还没有读过,你应该看看——它会让你更好地了解一个成熟的应用程序。但我希望这能让您基本了解如何使用布局和区域来显示不同的子应用视图

使用事件通过视图进行通信。在模型上引发这些事件(以便您甚至可以通过集合订阅它们)
<script id="artist-template" type="template/html">
  <%=firstName %> <%=lastName %>
</script>
<script id="booksApp-template" type="template/html">
  <div class="books"></div>
  <div class="authors"></div>
</script>
<script id="book-template" type="template/html">
  <img src="<%=bookThumbSrc %>" />
  <p><%=bookTitle %></p>
</script>
<script id="author-template" type="template/html">
  <%=firstName %> <%=lastName %>
</script>
$(document).ready({
  myApp.start();
  if(!Backbone.history.started) Backbone.history.start();
});
var myApp = new Backbone.Marionnette.Application();

myApp.addRegions({
  subAppRegion: "#sub_app"
});

// Your data
myApp.artists = new Backbone.Collection([...]);
myApp.books = new Backbone.Collection([...]);
myApp.module("musicApp", function(musicApp, myApp) {
  /* Setup your Views
   ================== */
  var MusicLayout = Backbone.Marionette.Layout.extend({
    template: #musicApp-template",
    regions: {
      albumsRegion: ".albums",
      artistsRegion: ".artists"
    }
  });

  var AlbumView = Backbone.Marionette.ItemView.extend({
    template: "#album-template"
  });

  var AlbumListView = Backbone.Marionette.CollectionView({
    itemView: AlbumView
  });

  var ArtistView = ...
  var ArtistListView = ...

  /* Create router for app navigation
   ==================================== */
  var Router = Backbone.Marionette.AppRouter.extend({
    appRoutes: {
      "music" : showMusicApp
    },
    controller: musicApp
  });
  new Router();

  /* Method to show the music app
   ================== */
  musicApp.showMusicApp = function() {
    // Instantiate Views
    var musicLayout = new MusicLayout();
    var albumListView = new AlbumListView({ collection: myApp.albums });
    var artistListView = new ArtistsListView({ collection: myApp.artists });

    // Show musicApp layout in subAppRegion of main app
    myApp.subAppRegion.show(musicLayout);

    // Show albums and artists in musicApp layout
    layout.albumsRegion.show(albumListView);
    layout.artistsRegion.show(artistListView);
  }
});
myApp.module("booksApp", function(booksApp, myApp) {
  ...
  var Router = Backbone.Marionette.AppRouter.extend({
    appRoutes: {
      "books" : showBooksApp
    },
    controller: booksApp
  });
  new Router();

  booksApp.showBooksApp = function() {
    ...
    myApp.subAppRegion.show(booksLayout)
    ...
  }
  ...
});