我目前正在编写一个Backbone Marionette应用程序,该应用程序最终会有大约6个不同的"屏幕"或页面,这些屏幕或页面通常会共享内容,我不确定如何最好地构建和访问Regions。
我使用的是这里描述的应用程序/模块设置:StackOverflow问题11070408:如何使用主干和require.js定义/使用多个路由。这将是一个随着时间的推移将添加新功能和内容的应用程序,需要可扩展(显然尽可能重复使用)
我正在构建的单页应用程序在每个屏幕上有4个主要部分:页眉、主要内容、次要内容、页脚。
页脚将在所有页面上保持一致,其中3页的页眉将相同,其余3页的页脚将略有修改(使用约80%的相同元素/内容)。"更多内容"区域将在不同的页面上重复使用。
在我的app.js文件中,我定义了我的区域,如下所示:
define(['views/LandingScreen', 'views/Header', 'router'], function(LandingScreen, Header, Router) {
"use strict";
var App = new Backbone.Marionette.Application();
App.addRegions({
header: '#mainHeader',
maincontent: '#mainContent',
morecontent: '#moreContent',
footer: '#mainFooter'
});
App.addInitializer(function (options) {
});
App.on("initialize:after", function () {
if (!Backbone.History.started) Backbone.history.start();
});
return App;
});
现在,回到前面文章中的应用程序设置,处理Regions的最佳方式是什么。我会在每个子应用程序中独立地重新声明每个区域吗?这似乎是保持模块尽可能独立的最佳方式。如果我走这条路,在子应用程序之间打开/关闭或隐藏/显示这些区域的最佳方式是什么?
或者,我是否保留在app.js中声明的Regions?如果是这样的话,我该如何最好地从子应用程序中更改和编排这些区域的事件?在app.js文件中定义Regions似乎违背了将模块和核心应用程序相互了解的信息保持在最低限度的直觉。此外,我看到的每个示例在主应用程序文件中都有appRegions方法。那么,从子应用程序访问和更改这些区域的最佳实践是什么?
提前感谢!
我实际上有一个根应用程序,它负责启动子应用程序,并在它们应该显示的区域中传递。我还使用了一个基于Backbone.SubRoute
的自定义组件,该组件支持子应用程序的相对路由。
看看这个要点:https://gist.github.com/4185418
您可以很容易地调整它,为定义多个区域的addRegions发送一个"config"对象,而不是我发送给子应用程序的start
方法的region
值
请记住,无论何时在Marionette中调用someRegion.show(view)
,它都会首先关闭其中当前显示的任何视图。如果您有两个不同的区域,每个区域都在自己的应用程序中定义,但都绑定到同一DOM元素,那么唯一重要的是最近调用了show
的区域。不过,这很混乱,因为您没有获得关闭前一个视图的优势——例如,取消绑定事件绑定器。
这就是为什么,如果我有一个子应用程序从某种根应用程序"继承"了一个区域,我通常只会将该根应用程序的实际区域实例传递给子应用程序,并将对该区域的引用保存为子应用程序的属性。这样,我仍然可以调用subApp.regionName.show(view)
,它运行得很好——如果你试图将事件从你的区域冒泡到你的应用程序,唯一可能出错的是你的事件链(因为该区域将属于根应用程序,而不是子应用程序)。我几乎总是使用Marionette.EventAggregator
的单独实例来管理事件,而不是依赖于区域/视图/控制器等的内置功能来解决这个问题。
也就是说,你可以两全其美——你可以将区域实例传递到你的子应用程序中,保存对它的引用,这样你就可以调用"关闭",然后使用它的regionInstance.el
属性来定义你自己的指向同一元素的区域实例。
for(var reg in regions) if regions.hasOwnProperty(reg) {
var regionManager = Marionette.Region.buildRegion(regions[reg].el,
Marionette.Region);
thisApp[reg] = regionManager;
}
这完全取决于你的优先事项。
我个人更喜欢在我的Marionette应用程序中使用模块。我觉得它消除了require.js给您的应用程序增加的复杂性。在我目前正在开发的一个应用程序中,我创建了一个定义主干应用程序的app.js文件,但我使用的是一个控制器模块,它加载我的路由、填充我的集合并填充我的区域。
app.js->
var app = new Backbone.Marionette.Application();
app.addRegions({
region1: "#region1",
region2: "#region2",
region3: "#region3",
region4: "#region4"
});
app.mainapp.js->
app.module('MainApp', function(MainApp, App, Backbone, Marionette, $, _) {
// AppObjects is an object that holds a collection for each region,
// this makes it accessible to other parts of the application
// by calling app.MainApp.AppObjects.CollectionName....
MainApp.AppObjects = new App.AppObjects.Core();
MainApp.Controller = new Backbone.Marionette.Controller.extend({
start: function() {
// place some code here you want to run when the controller starts
} //, you can place other methods inside your controller
});
// This code is ran by Marionette when the modules are loaded
MainApp.addInitializer(function() {
var controller = new MainApp.Controller();
controller.start();
});
});
然后,您可以将您的路由放置在控制器中访问的另一个模块中。
然后在网页中,你可以通过调用来启动一切。
$(function () {
app.start();
});
Marionette将自动运行并加载您的所有模块。
我希望这能让你从某个方向开始。很抱歉,我无法复制并通过整个应用程序代码来为您提供更好的示例。一旦这个项目完成,我将重新创建一个演示应用程序,我可以推送到网上。