2

我目前正在编写一个 Backbone Marionette 应用程序,该应用程序最终相当于大约 6 个不同的“屏幕”或页面,它们经常共享内容,我不确定如何最好地构建和访问区域。

我正在使用此处描述的应用程序/模块设置: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;
});

现在,回到前面提到的帖子中的应用程序设置,处理区域的最佳方式是什么。我会在每个子应用程序中独立地重新声明每个区域吗?这似乎是保持模块尽可能独立的最佳方式。如果我走那条路,在子应用程序之间打开/关闭或隐藏/显示这些区域的最佳方式是什么?

或者,我是否保留 app.js 中声明的区域?如果是这样,那么我将如何最好地从子应用程序中更改和协调这些区域的事件?在 app.js 文件中定义区域似乎与将模块和核心应用程序相互了解的内容保持在最低限度有悖常理。另外,我看到的每个示例在主应用程序文件中都有 appRegions 方法。那么从子应用访问和更改这些区域的最佳实践是什么?

提前致谢!

4

2 回答 2

4

我实际上有一个负责启动子应用程序的根应用程序,它通过它们应该显示的区域。我还使用了一个基于它的自定义组件,Backbone.SubRoute它为子应用程序启用了相对路由。

看看这个要点:https ://gist.github.com/4185418

您可以轻松地调整它以发送定义多个区域的 addRegions 的“配置”对象,而不是region我发送给子应用程序start方法的值

请记住,每当您调用someRegion.show(view)Marionette 时,它​​将首先关闭当前显示在其中的任何视图。如果您有两个不同的区域,每个区域都在其自己的应用程序中定义,但它们都绑定到同一个 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;
}

这一切都取决于你的优先事项是什么。

于 2012-12-11T22:19:52.193 回答
2

我个人更喜欢在我的 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 将自动运行并加载您的所有模块。

我希望这能让你朝着某个方向开始。抱歉,我无法复制并粘贴整个应用程序代码,以便为您提供更好的示例。这个项目完成后,我将重新创建一个可以推送到网络的演示应用程序。

于 2012-12-04T01:17:19.527 回答