186

希望有人可以分享他们对一些最新出现的backbone.js 变体的经验。我在几个项目中在主干/下划线/需求方面有一些很好的经验,我想朝着更高级的复杂应用程序结构解决方案迈出下一步。

我知道以下框架可用:

可能我错过了一些。

这里有一个关于差异的简短介绍:

但它很笼统。我想知道是否有人可以分享他们使用这些框架在现实生活中的应用程序的经验。

选择其中一个有什么好处?例如,木偶什么时候会成为比卓别林更好的解决方案,或者为什么椎骨更适合某些应用。

当然,显而易见的答案将是“使用最适合您需要的东西”,但我缺乏使用这些框架的经验来了解它们的强度/目的/优势或首选方案。

谢谢!

编辑 1: 找到这篇文章: Backbone.Marionette vs Backbone-Boilerplate

编辑 2: Mathias schafer(卓别林)通过邮件回答:

简而言之,当前的结构接近于 1.0 版,因为它已经在生产中使用。我们不打算在 1.0 之前添加大的新功能或破坏 API 更改。

Marionette 肯定是目前最全面、最稳定的库。它解决了使用 Backbone 开发 JS 应用程序的几个方面。例如,它有一个强大的视图层,Backbone 本身完全无效。当然,你会发现有些方面并不能满足你的要求,你可能会觉得有必要围绕木偶搭建一个结构。

相比之下,卓别林专注于 Backbone 应用程序的一个很小但非常重要的方面,即整体应用程序结构和模块生命周期。在这方面,卓别林非常自以为是,更像是一个框架而不是一个库(就像“你的代码调用一个库,一个框架调用你的代码”)。Chaplin 提供了一些位于各个应用程序模块之上并控制整个应用程序状态的中心类。这为您的应用程序提供了一个传统的结构,例如 Ruby on Rails。

在 Chaplin 中,您声明了一些映射到控制器的路由,并且一旦路由匹配,Chaplin 就会启动控制器。它还负责处理旧控制器,以及显示和隐藏控制器应该创建的主视图。这是基本的想法,但卓别林会处理丑陋的细节以使其顺利运行。

这种结构有两个原则: - 模块化、解耦和沙盒 - 使用发布/订阅和中介者的跨模块通信

当然,这些模式在软件开发领域并不新鲜,而且卓别林并不是唯一将它们应用于 Backbone.js 应用程序的库。

Chaplin 还为 View 层提供了增强功能,例如高度复杂的 CollectionView,但总体上不如 Marionette 及其区域和布局。但是使用卓别林视图提供的方法编写这样的元类相对容易。

4

5 回答 5

132

您正在研究的大多数(全部?)框架都解决了相同的问题,但它们以略有不同的方式来解决问题,目标也略有不同。

我认为可以公平地说,所有这些项目都会解决这些类别的问题:

  • 提供一组合理的默认值
  • 减少样板代码
  • 在 BackboneJS 构建块之上提供应用程序结构
  • 提取作者在其应用程序中使用的模式

我从 2011 年 12 月开始制作的 Marionette 也有一些非常明确的目标和理想:

  • 复合应用架构
  • 企业消息传递模式影响
  • 模块化选项
  • 增量使用(没有全有或全无要求)
  • 没有服务器锁定
  • 轻松更改这些默认值
  • 代码作为配置/过度配置

我并不是说其他​​框架都没有这些相同的目标。但我认为 Marionette 的独特性来自于这些目标的结合。

复合应用架构

我在使用 WinForms 和 C# 的胖客户端分布式软件系统中工作了 5 年多。我为台式机、笔记本电脑(智能客户端)、移动设备和 Web 应用程序构建了应用程序,它们都共享一个核心功能集并多次使用相同的服务器后端。在这段时间里,我了解了模块化的价值,并很快走上了复合应用程序设计的道路。

基本思想是“组合”应用程序的运行时体验并处理许多较小的、不一定相互了解的单独部分。它们向整个复合应用系统注册自己,然后通过各种解耦消息和调用的方式进行通信。

我在我的博客上写过一些关于这个的文章,介绍 Marionette 作为 Backbone 的复合应用程序架构:

消息队列/模式

同样大规模的分布式系统还利用消息队列、企业集成模式(消息传递模式)和服务总线来处理消息。最重要的是,这对我的解耦软件开发方法产生了巨大影响。我开始从这个角度看待单进程、内存中的 WinForms 应用程序,很快我的服务器端和 Web 应用程序开发也受此影响。

这直接转化为我对 Backbone 应用程序设计的看法。我在 Marionette 中为高级应用程序对象和您在应用程序中创建的每个模块提供了一个事件聚合器。

我考虑可以在我的模块之间发送的消息:命令消息、事件消息等等。我还将服务器端通信视为具有这些相同模式的消息。有些模式已经进入 Marionette,但有些还没有。

模块化

代码的模块化非常重要。对于任何具有显着规模和复杂性的系统,都必须创建具有明确定义的入口和出口点的小型、封装良好的封装。

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 视图。这些应用程序还需要在新视图到位时处理关闭旧视图并清理内存。这就是 Marionette'sRegion发挥作用的地方。区域处理获取视图、在其上调用渲染以及将结果填充到 DOM 中的样板代码。然后将关闭该视图并为您清理它,前提是您的视图上有一个“关闭”方法。


MyApp.addRegions({
  someRegion: "#some-div"
});

MyApp.someRegion.show(new MyView());

但是您不需要使用 Marionette 的视图来使用区域。唯一的要求是您在对象原型链中的某个点从 Backbone.View 扩展。如果您选择提供close方法、onShow方法或其他方式,木偶区会在合适的时间为您调用。

无服务器锁定

我在各种服务器技术之上构建 Backbone / Marionette 应用程序:

  • ASP.NET MVC
  • Ruby on Rails
  • 红宝石/西纳特拉
  • NodeJS / ExpressJS
  • PHP / 苗条
  • 爪哇
  • 二郎
  • ... 和更多

当涉及在浏览器中运行时,JavaScript 就是 JavaScript。服务器端 JavaScript 也很棒,但它对我如何编写基于浏览器的 JavaScript 的影响或影响为零。

由于我构建的项目和客户使用的后端技术的多样性,我不能也不会出于任何原因将 Marionette 锁定在单个服务器端技术堆栈中。我不会提供样板项目。我不会提供 ruby​​ gem 或 npm 包。我希望人们了解 Marionette 不需要特定的后端服务器。它是基于浏览器的 JavaScript,后端无关紧要。

当然,我完全支持其他人为他们的语言和框架提供包。我在 Wiki 中列出了这些包,并希望人们在看到需要时继续构建更多包。但这是社区支持,而不是 Marionette 的直接支持。

轻松更改默认值

为了减少样板代码并提供合理的默认值(这是我直接从 Tim Branyen 的 LayoutManager 中“借用”的一个想法),我认识到其他开发人员需要使用与我略有不同的实现。

我提供基于<script>模板内联标签的渲染,默认使用 Underscore.js 模板。但是您可以通过更改Marionette 中的Renderer和/或对象来替换它。TempalteCache这两个对象提供了渲染功能的核心,并且有一些 wiki 页面展示了如何针对特定的模板引擎和加载模板的不同方式进行更改。

使用 Marionette v0.9,它变得更加容易。例如,如果你想用预编译的模板替换内联模板脚本块的使用,你只需要替换 Renderer 上的一种方法:


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 的工作方式。

于 2012-06-13T13:50:15.257 回答
25

我目前正在使用带有布局管理器模块和把手的主干作为模板引擎,我发现使用已经存在的 Grails 后端设置一个小应用程序非常容易。在开始使用布局管理器之前,我阅读了有关木偶和卓别林的文章,在我看来两者都非常强大但复杂。然后我想起了我最初选择backbone.js的原因:简单。所有这些框架都在添加主干设计中遗漏的内容。我并不是说一个框架不好,但是如果我需要更复杂的东西,我会尝试其他项目,比如 ember.js 或 sproutcore,因为它们有一个独特的代码库,并且在他们的开发人员心中有一个目标。在这里,我们在另一个框架之上有框架。当然,主干不仅是构建应用程序的主干,也是编写一些更强大的库的主干,但我认为唯一真正糟糕的是视图层,因为缺少布局管理器和嵌套视图的可能性。使用布局管理器可以很好地填补空白。

所以,我对你的问题的回答是:从按原样使用主干开始,问问自己缺少什么以及你对框架的期望是什么。如果你发现主干遗漏了太多东西,那就去其他框架中搜索它们,然后选择最接近你需要的那个。如果你仍然对选择没有信心,也许主干不适合你,你必须寻找其他解决方案(ember.js、sproutcore、ExtJs、JavaScript MVC 都很好)。如果您有编写客户端应用程序的经验,那么您实际上并不需要所有框架的经验来选择合适的框架(当然是对您而言)

于 2012-06-05T21:18:39.860 回答
13

我在 BenchPrep 工作时开发了Luca 框架,我们用它在主干.js 库之上开发了几个大型单页应用程序。

几年前我使用 ExtJS 并从该框架中窃取了我最喜欢的概念,例如组件驱动的架构,您将视图开发为独立组件,然后使用容器视图将它们与其他组件连接在一起。由于它在很大程度上基于配置,因此在 Luca 中开发应用程序感觉很像用 JSON 描述对象。

这种方法的一个优点是能够跨多个应用程序或在应用程序的不同位置重用组件,只需使用 Backbone 的扩展进行微小的更改。只需对 JSON 配置进行细微调整,就可以很容易地尝试许多不同的组件布局/表示。

除了广泛的辅助/实用功能之外,Luca 还提供了许多更高级别的 Backbone 衍生产品,您可以以任何可以想象的方式拼凑起来以构建复杂的 UI。

视图、组件、容器

  • 增强模型、视图、集合、路由器类
  • 便于模型、集合、视图、应用程序及其各自管理器之间通信的配置选项。
  • 容器(拆分/列布局、网格布局、选项卡视图、卡片/向导视图)
  • 带有所有标准字段组件的 FormView,以及用于与 Backbone.Model 同步的助手
  • GridView,用于从 Luca.Collection 生成可滚动的网格元素
  • CollectionView,用于基于集合生成视图
  • 工具栏/按钮

Twitter Bootstrap 样式和标记免费

  • Luca 与 Twitter 引导框架配合得非常好。只需设置 Luca.enableBootstrap = true 并包含 CSS,您的组件(例如选项卡视图、工具栏、按钮、表单、字段、网格等)将自动使用 Twitter Bootstrap 兼容标记和 CSS 类约定。
  • 使用 Grid 系统进行布局,并以智能方式响应大多数 bootstrap 基础 css 类
  • Luca.Viewport 和 GridLayout 组件设置为与引导程序的响应式、流体或静态网格系统一起使用。
  • 旨在为 twitter 引导组件提供一对一匹配,以将它们表示为可配置的主干视图

应用程序组件

  • 基于 Backbone.Model 的状态机提供 getter/setter 方法和属性更改事件作​​为应用程序控制流的一种样式
  • 集成控制器组件,它隐藏/显示应用程序页面以响应 Backbone.Router 或状态机事件
  • 集成的集合管理器跟踪您创建的集合,允许您对它们进行范围、分组、为它们分配默认参数
  • 一个套接字管理器,它是 websocket 服务之上的一个抽象层,它使推送像 Backbone.Event 一样简单
  • 一个键盘事件路由器,它在关心响应此类事件的组件上触发命名键事件

集合和模型增强

  • 集合基于主干查询,它提供了一个非常类似于 mongoDb 的查询接口
  • 只需设置 collection.localStorage = true 即可启用本地存储 Backbone.sync
  • 自动填充其数据在页面加载时引导的集合
  • 缓存方法/计算属性。缓存集合方法的结果,并过期缓存以响应集合或其模型上的更改/添加/删除事件
  • 模型上的计算属性。基于复杂函数构建属性,并根据变化自动更新计算值

事件和挂钩

与库存的 Backbone 组件相比,Luca 组件在它们发出的事件方面更加自由。它们将发出诸如 before:initialize、after:initialize、before:render、after:render、activation、first:activation、deactivation、first:deactivation 之类的事件,这使您可以更精细地调整组件的行为。另外,通过在视图的@hooks 属性中定义一个事件,它会自动为您调用一个类似命名的函数(如果存在)。这可以防止许多提高可读性的回调样式代码。

您还可以配置 Luca.Events 类以将事件发布到全局发布/订阅通道,这使得构建大型应用程序更容易并有助于模块间通信。

红宝石

Luca 是专门针对 Rails 和 Sinatra API 开发的,因此目前针对特定堆栈进行了优化,但它绝不会将您锁定在特定服务器中。

Luca 作为配置为在资产管道上工作的 Ruby Gem 的一部分分发,或者作为可下载的 JS 文件分发。

您不需要使用 Rails 或 Sinatra。但如果你这样做,我已经包含了很多有用的东西:

  • 带有 .luca 扩展名的文件被处理为带有 JST 样式变量插值的 HAML。(相当于 .jst.ejs.haml )由资产管道
  • 用于浏览器的测试工具,或基于 Jasmine 的无头单元测试以及许多 Backbone 和 Underscore 测试助手。
  • Luca 附带的开发工具集的 API 端点(稍后会详细介绍)
  • 一个 API 端点,允许您以最少的配置将 Redis 用作 Luca.Collection 的无模式存储引擎

开发工具

  • Luca 应用程序可以使用 Luca 特定的帮助程序和命令启用浏览器内的咖啡脚本控制台,以帮助监视、检查、调试 Luca 应用程序和组件

由 CoffeeScript 提供支持的浏览器开发控制台中的 Luca 示例

  • 在 Rails Gem 和 Luca 基于 CodeMirror 的组件编辑器的帮助下,您可以使用 Coffeescript 直接在浏览器中编辑 Luca Framework 的源代码以及应用程序特定的组件。您将看到对您的编辑的即时反馈,受影响对象的实例将使用更新的原型进行刷新,并且您可以将更改保存到磁盘。

  • 组件测试器是一个实时沙箱,用于单独使用构成应用程序的组件。它为您提供了用于修改组件原型、设置其依赖项和配置组件的工具。每次您进行编辑时,组件都会立即重新渲染。您可以直接在浏览器中查看和编辑组件生成的标记以及 CSS,并立即查看您的更改。这使它成为一个非常有价值的实验工具。

  • 组件测试器将很快与 Jasmine 集成,因此您可以在编辑其代码时实时查看组件单元测试的结果

组件测试仪截图

Luca 是一项正在进行中的工作,但维护了一个稳定的 API(还没有 1.0),并且已经在几个大型生产应用程序中使用。它绝对是一个非常自以为是的框架,但我正在努力使其更加模块化。我正在积极处理文档和示例组件。

于 2012-06-21T04:10:51.210 回答
13

我研究了使用 Backbone.js 构建的各种框架,并为 HauteLook 的一个项目构建了 Vertebrae。项目目标包括...动态脚本加载、AMD 模块格式、依赖管理、使用大部分开源库构建、组织包中的代码、优化和构建一个或多个单页应用程序、托管在完全缓存的服务器上,例如无服务器- 仅使用数据 API 编写脚本,对我来说最有趣的是,对项目使用行为驱动的开发。该项目的描述位于:http ://www.hautelooktech.com/2012/05/24/vertebrae-front-end-framework-built-with-backbone-js-and-requirejs-using-amd/

我们的问题:

选定的库(jQuery、Underscore.js、Backbone.js、RequireJS、Mustache)提供模块加载、依赖管理、应用程序结构(用于模型、集合、视图和路由)、与 API 的异步交互、各种实用程序和对象来管理异步行为,例如(承诺)延迟、回调。完成框架所需的其余逻辑包括:

  • 管理单页应用程序状态的对象(模型);
  • 一个布局管理器,用于呈现、排列/转换和清除视图,以及
  • 响应路由、获取/设置应用程序状态并将工作移交给布局管理器的控制器。

我们的解决方案(在 Vertebrae 中实施):

应用程序状态管理器-

应用程序管理器将数据存储在内存中,并将数据持久存储在浏览器存储中,以为公共数据/元数据提供资源。还提供数据(状态)以根据先前的交互(例如选择的选项卡、应用的过滤器)重建页面视图。应用程序状态管理器提供资源检索状态的策略。旨在充当状态机。

布局管理器-

布局管理器具有一个或多个视图以及每个(渲染的)视图的文档(DOM)目的地。一个页面可以在许多视图之间转换,因此布局管理器跟踪视图状态,例如渲染、未渲染、显示、未显示。您可以使用布局管理器延迟加载和呈现站点访问者很可能请求的(分离的)视图,例如页面上的选项卡更改。视图状态之间的转换由该对象管理。可以清除整个布局,以便删除视图对象及其绑定,为垃圾收集准备这些对象(防止内存泄漏)。布局管理器还与控制器通信视图状态。

控制器-

控制器对象由路由处理函数调用,负责获取相关状态(应用程序模型)以生成页面(布局),(还负责在路由更改时设置状态)。控制器将所请求页面的相关数据(模型/集合)和构造的视图对象传递给布局管理器。作为副作用,控制器的使用可以防止路由对象变得臃肿和混乱。路由应该映射到控制器,然后控制器启动页面视图,保持路由处理功能精简。

Todos 应用程序在开发模式下托管并在 Heroku 上进行了优化...

借用了其他框架中的许多概念,例如 Derick Bailey 指出的需要破坏视图来预览内存泄漏 - http://lostechies.com/derickbailey/;Tim Branyen 的布局管理器http://tbranyen.github.com/backbone.layoutmanager/

总之,Backbone.js 旨在成为您应用程序中的一个工具,Backbone.js 库不提供构建应用程序所需的所有架构,但确实提供了与 API 和可靠代码结构的良好交互...视图(也像控制器一样)和你的数据层模型和集合,最后是路由。我们构建 Vertebrae 以实现我们项目的目标,并决定将代码提取为框架供其他人使用、学习或其他。

我认为你的问题的答案是从所有框架中学习并使用你需要的东西来实现你的目标,如果你发现你的项目目标与使用 Backbone 构建的框架之一非常吻合,那么很好,否则构建你自己的框架社区分享了很多很好的例子。或者,如果您发现自己在应用程序的方向上有点迷失,那么选择一些更有主见和结构化的东西,也许是 Ember.js。很棒的事情是有各种各样的选择可以帮助您使用 (MVX) MVC 之类的模式和 JavaScript 进行编码。

于 2012-06-05T22:34:31.620 回答
11

我是 Chaplin 的合著者,我在 Chaplin.js 和 Marionette.js 之间进行了深入比较:

http://9elements.com/io/index.php/comparison-of-marionette-and-chaplin/

这不是“枪战”,而是试图以平衡的方式解释这两种方法。

于 2013-04-11T09:28:07.120 回答