您正在查看的大多数(全部?)框架都解决相同的问题,但它们的实现方式略有不同,目标也略有不同。
我认为可以公平地说所有这些项目都会解决以下类别的问题:
- 提供一组合理的默认值
- 减少样板代码
- 在 BackboneJS 构建块之上提供应用程序结构
- 提取作者在应用程序中使用的模式
我自 2011 年 12 月以来一直在构建 Marionette,它也有一些非常明确的目标和理想:
- 复合应用架构
- 企业消息传递模式影响
- 模块化选项
- 增量使用(没有全有或全无的要求)
- 没有服务器锁定
- 轻松更改这些默认值
- 代码作为配置/过度配置
我并不是说其他框架都没有这些相同的目标。但我认为 Marionette 的独特性来自于这些目标的结合。
复合应用架构
我在使用 WinForms 和 C# 的胖客户端分布式软件系统中工作了 5 年多。我为台式机、笔记本电脑(智能客户端)、移动设备和 Web 应用程序构建了应用程序,所有应用程序共享核心功能集并多次使用相同的服务器后端。这次,我了解了模块化的价值,并很快走上了复合应用程序设计的道路。
基本思想是“组合”应用程序的运行时体验,并由许多彼此不一定了解的较小的单独部分组成。它们将自己注册到整个组合应用程序系统中,然后通过各种解耦消息和调用的方式进行通信。
我在我的博客上写了一些相关内容,介绍了 Marionette 作为 Backbone 的复合应用程序架构:
- http://lostechies.com/derickbailey/2011/11/17/introduction-to-composite-javascript-apps/ http://lostechies.com/derickbailey/2011/11/17/introduction-to-composite-javascript-apps/
- http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/ http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
消息队列/模式
同样的大规模分布式系统也利用消息队列、企业集成模式(消息传递模式)和服务总线来处理消息。这比其他任何事情都对我的解耦软件开发方法产生了巨大的影响。我开始从这个角度看待单进程、内存中的 WinForms 应用程序,很快我的服务器端和 Web 应用程序开发就受到了影响。
这直接转化为我对 Backbone 应用程序设计的看法。我在 Marionette 中为高级应用程序对象以及您在应用程序中创建的每个模块提供了一个事件聚合器。
我考虑了可以在模块之间发送的消息:命令消息、事件消息等等。我还将服务器端通信视为具有这些相同模式的消息。有些图案已经出现在 Marionette 中,但有些还没有。
- http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/ http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/
- http://lostechies.com/derickbailey/2012/04/03/revisiting-the-backbone-event-aggregator-lessons-learned/ http://lostechies.com/derickbailey/2012/04/03/revisiting-the-backbone-event-aggregator-lessons-learned/
-
http://lostechies.com/derickbailey/2009/12/23/understanding-the-application-controller-through-object-messaging-patterns/ http://lostechies.com/derickbailey/2009/12/23/understanding-the-application-controller-through-object-messaging-patterns/(WinForms代码,但仍然适用)
模块化
代码的模块化非常重要。对于任何具有显着规模和复杂性的系统来说,都必须创建小型、封装良好、具有明确入口和出口点的单一焦点的包。
Marionette 直接通过它的module
定义。但我也认识到有些人喜欢 RequireJS 并且想要使用它。因此,我提供了标准构建和 RequireJS 兼容构建。
MyApp = new Backbone.Marionette.Application();
MyApp.module("MyModule", function(MyModule, MyApp, Backbone, Marionette, $, _){
// your module code goes here
});
(目前还没有可用的博客文章)
增量使用
这是我尽可能融入 Marionette 各个部分的核心理念之一:使用 Marionette 时没有“全有或全无”的要求。
Backbone 本身采用了一种非常增量和模块化的方法来处理它的所有构建块对象。您可以自由选择要使用哪些、何时使用。我坚信这一原则,并努力确保 Marionette 以同样的方式工作。
为此,我在 Marionette 中内置的大部分组件都是独立构建的,可以与 Backbone 的核心组件配合使用,并且可以更好地协同工作。
例如,几乎每个 Backbone 应用程序都需要在屏幕上的特定位置动态显示 Backbone 视图。应用程序还需要在新视图到位时关闭旧视图并清理内存。这就是木偶的地方Region
进来玩。区域会处理获取视图、调用渲染并将结果填充到 DOM 的样板代码。然后将关闭该视图并为您清理它,前提是您的视图具有“关闭”方法。
MyApp.addRegions({
someRegion: "#some-div"
});
MyApp.someRegion.show(new MyView());
但是您不需要使用 Marionette 的视图来使用区域。唯一的要求是您要在对象原型链中的某个点从 Backbone.View 进行扩展。如果您选择提供close
方法,一个onShow
方法,或者其他,秘偶区会在适当的时候为你调用。
- http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/ http://lostechies.com/derickbailey/2011/12/12/composite-js-apps-regions-and-region-managers/
- http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/ http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/
无服务器锁定
我在各种服务器技术之上构建 Backbone / Marionette 应用程序:
- ASP.NET MVC
- 红宝石 on Rails
- 红宝石/西纳特拉
- NodeJS / ExpressJS
- PHP / 苗条
- Java
- Erlang
- ... 和更多
当谈到在浏览器中运行时,JavaScript 就是 JavaScript。服务器端 JavaScript 也很棒,但它对我如何编写基于浏览器的 JavaScript 的影响为零。
由于我构建的项目和客户使用的后端技术的多样性,我不能也不会出于任何原因将 Marionette 锁定到单个服务器端技术堆栈。我不会提供样板项目。我不会提供 ruby gem 或 npm 包。我希望人们了解 Marionette 不需要特定的后端服务器。它是基于浏览器的 JavaScript,后端并不重要。
当然,我完全支持其他人为他们的语言和框架提供包。我在 Wiki 中列出了这些软件包,并希望人们在看到需要时继续构建更多软件包。但这是社区支持,而不是来自 Marionette 的直接支持。
- https://github.com/derickbailey/backbone.marionette/wiki/Available-packages https://github.com/derickbailey/backbone.marionette/wiki/Available-packages
轻松更改默认值
在我努力减少样板代码并提供合理的默认值(这是我直接从 Tim Branyen 的 LayoutManager 中“借用”的想法)时,我认识到其他开发人员需要使用与我略有不同的实现。
我提供基于内联的渲染<script>
模板的标签,默认使用 Underscore.js 模板。但您可以通过更改来替换它Renderer
and/or TempalteCache
木偶中的对象。这两个对象提供了渲染功能的核心,并且有 wiki 页面展示了如何针对特定模板引擎和加载模板的不同方式更改此功能。
有了 Marionette v0.9,事情变得更加容易。例如,如果您想用预编译模板替换内联模板脚本块的使用,则只需替换渲染器上的一种方法:
Backbone.Marionette.Renderer.render = function(template, data){
return template(data);
};
现在整个应用程序将使用您附加到视图的预编译模板template
属性。
我什至在 v0.9 中提供了 Marionette.Async 插件,它允许您支持异步渲染视图。我不断努力让替换 Marionette 中的默认行为尽可能简单。
代码即配置
在某些情况下,我是“约定优于配置”的粉丝。这是一种完成工作的强大方式,Marionette 提供了一点点 - 虽然不是太多,老实说。许多其他框架 - 特别是 LayoutManager - 提供了比 Marionette 更多的配置约定。
这是有目的和意图的。
我已经构建了足够多的 JavaScript 插件、框架、附加组件和应用程序,以了解尝试让约定以有意义且快速的方式工作的痛苦。它可以快速完成,但通常是以无法改变它为代价的。
为此,我对 Marionette 采用“代码即配置”方法。我没有提供很多“配置”API,您可以在其中提供带有静态值的对象文字,从而改变一系列行为。相反,我通过带注释的源代码和实际的 API 文档记录了每个对象具有的方法,目的是告诉您如何更改 Marionette 以按照您想要的方式工作。
通过为 Marionette 对象提供干净清晰的 API,我创建了一种情况,即替换特定对象或整个 Marionette 的行为相对简单且非常灵活。我牺牲了“简单”的配置 API 调用,以换取提供您自己的代码的灵活性,使事情按照您想要的方式工作。
您在 Marionette 中找不到“配置”或“选项”API。但您会发现大量方法,每个方法都有一个非常特定的目的,并且具有清晰的签名,可以轻松更改 Marionette 的工作方式。