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

时间:2012-07-09 10:39:01

标签: backbone.js marionette

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

我有一个可以轻松构建到不同子应用程序(也称为Backbone模块)的应用程序 点击我主导航栏中的链接即可启动其中一个应用。这意味着它将启动布局的应用加载到我的#main div。

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

e.g。

var myApp = Backbone.Marionette.Application()
...
var layout = myApp.myModule.layout = new Backbone.Marionette.Layout()
...
myApp.main.show(myApp.myModule.layout)

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

#app_main
  .albums
  .artists

然后我做了类似

的事情
layout.app_main.show(new myView())

从现在开始,即使使用后退按钮(使用Backbone.Router和History),我也无法访问layout.albums或layout.artists

我应该将模块的主要布局拆分为仅包含#app_main,并在单独的步骤中将开放布局加载到其中吗?或者您有其他想法吗?

2 个答案:

答案 0 :(得分:3)

了解你的目标会有所帮助,但这里有一个答案。让我知道它是否有帮助!

假设这是您的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 -->

对于我们的“音乐”子应用,我们将使用此模板:

<script id="musicApp-template" type="template/html">
  <div class="albums"></div>
  <div class="artists"><div>
</script>

对于专辑项目视图:

<script id="album-template" type="template/html">
  <img src="<%=albumThumbSrc %>" />
  <p><%=albumTitle %></p>
</script>

对于艺术家项目视图:

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

-

现在设置我们的木偶视图。

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

我还没有测试过所有这些代码,很抱歉,如果有一些问题,我相信它可以改进。

如果您还没有阅读David Sulc's tutorial,那么您应该看一下 - 它会让您更好地了解完整的应用程序。但我希望这能让您基本了解如何使用布局和区域来显示不同的子视图。

答案 1 :(得分:0)

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

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