【问题标题】:how to lay out a complex app and its views/regions/layouts如何布局一个复杂的应用程序及其视图/区域/布局
【发布时间】:2012-07-09 10:39:00
【问题描述】:

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

我有一个可以轻松构建成不同子应用(又名主干模块)的应用 单击主导航栏中的链接可启动其中一个应用程序。这意味着它将应用程序开始布局加载到我的#main div中。

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

例如

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

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

#app_main
  .albums
  .artists

然后我做类似的事情

layout.app_main.show(new myView())

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

我是否应该将模块的主布局拆分为仅包含#app_main,并在单独的步骤中将打开的布局加载到其中?或者你有什么其他想法?

【问题讨论】:

  • 使用事件通过视图进行通信。在模型上引发这些事件(这样您甚至可以通过集合订阅它们)

标签: backbone.js marionette


【解决方案1】:

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

假设这是您的 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();
});

--

现在设置我们的 Marionette 视图。

在 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,您应该看一下 - 它会让您更好地了解完整的应用程序。但我希望这能让你对如何使用布局和区域来显示不同的 subApp 视图有一个基本的了解。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      相关资源
      最近更新 更多