Backbone Marionette使用Require.js,Regions以及如何设置

时间:2012-12-01 05:08:06

标签: backbone.js marionette singlepage regions single-page-application

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

我正在使用此处描述的应用/模块设置: StackOverflow question 11070408: How to define/use several routings using backbone and 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文件中定义区域似乎与保持哪些模块和核心应用程序相互了解至少相反。另外,我看到的每个示例都在主app文件中有appRegions方法。那么从子应用程序访问和更改这些区域的最佳做法是什么?

提前致谢!

2 个答案:

答案 0 :(得分:4)

我实际上有一个根应用程序负责启动子应用程序,它会在它们应该显示的区域中传递。我还使用基于Backbone.SubRoute的自定义组件,该组件支持子应用程序的相对路由。

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

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

请记住,无论何时在Marionette中呼叫someRegion.show(view),它都会先关闭当前显示的任何视图。如果你有两个不同的区域,每个区域都在自己的应用程序中定义,但两者都绑定到同一个DOM元素,唯一重要的是哪个区域最近调用了show。但是,这很麻烦,因为你没有获得关闭前一个视图的优势 - 例如解除绑定的事件绑定器。

这就是为什么,如果我有一个从某种根应用程序“继承”某个区域的子应用程序,我通常只是将实际区域实例从该根应用程序传递到子应用程序,并保存对该区域作为子应用程序的属性。这样我仍然可以调用subApp.regionName.show(view)并且它完美无缺 - 如果您尝试将事件从您的区域冒泡到您的应用程序(因为该区域将属于root app,而不是sub-app)。我几乎总是使用Marionette.EventAggregator的单独实例来管理事件,而不是依赖于regions / views / controllers /等的内置功能,从而解决了这个问题。

也就是说,您可以充分利用这两个世界 - 您可以将区域实例传递到您的子应用程序中,保存对它的引用,以便您可以调用“close”,然后使用其regionInstance.el属性定义指向同一元素的您自己的区域实例。

for(var reg in regions) if regions.hasOwnProperty(reg) {
    var regionManager = Marionette.Region.buildRegion(regions[reg].el,
            Marionette.Region);
    thisApp[reg] = regionManager;
}

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

答案 1 :(得分: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将自动运行并加载所有模块。

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