计划,每天学习两小时,坚持带来大改变。

Marionettejs 全面介绍 (1)

前端开发 阿尤 2607浏览 0评论

粗略地与翻译自 Smashing Magazine:

Backbonejs正在变得越来越流行,但不像Emberjs(译者按:Angularjs也是),Backbone因为他的最小化,使得大量的问题留给了开发者需要自己想办法解决。

所以,一旦你介入到了一个更复杂的应用,Backbone就变得不那么简单了(虽然这本来是他的优点)。Marionette就是来解决这种Backbone开发的、逐渐出现的痛苦。

中心App对象

大多数人做一个Backbone App时都会先整一个中心对象并把所有的东西绑在上面,通常命名为App或Application。但Backbone本身不提供这个功能,所以很多人直接使用Router作为这个对象。当然有App对象总比没有的强,但Router却不是设计来做这类事的。

Derick Bailey,Marionettejs的作者有一个更好的解决方案:他创建了一个Class来专门做这类事。你可以这样创建一个App: var App = new Backbone.Marionette.Application(),然后,当一切就绪时,这样启动App:App.start(options)。我们之后会讨论那个options是用来做啥的。

初始化器 Initializers

Marionette.Application 最酷的地方就是Initializers。当你的代码是模块化时,应用启动时会有许多东西需要初始化。比起把一切初始化过程都放在main.js里面,你可以把初始化的过程直接放到Module文件里(译者按:这样做,似乎不太好吧……),像这样:

var SomeModule = function(o){ // SomeModule的创建器 }; App.addInitializer(function(options) { App.someModule = new SomeModule(options); }); 

所有通过这种方式添加的Initializer都会在App.start被调用的时候运行。注意,options参数会被传入每一个initializer方法,这就是你在调用App.start(options);时所传入的对象。这是传入处理不同的应用配置的绝佳方法,并且所有的模块都能使用它。

一些事件也会在这些Initializer调用过程中被触发:

initialize:before:在所有Initializer调用前触发; initialize:after: 在所有Initializer都完成之后触发; start:在initialize:after之后触发。

你可以监听这些事件进行更多的控制,比如:

App.on('initialize:before', function(options) { options.anotherThing = true; // Add more data to your options }); App.on('initialize:after', function(options) { console.log('Initialization Finished'); }); App.on('start', function(options) { Backbone.history.start(); // Great time to do this }); 

非常简单,却可以增加你的应用的灵活性。

事件汇合器 Event Aggregator

Application对象还通过使用事件汇合器给予Backbone App更多的解耦的可能性。之前我写过一篇文章Scalable Javascript Applications,里面我有提过,系统中的每一个模块都应该完全独立于其它模块,然后他们能通信于其它模块的唯一方法就是通过全局对象的事件。通过这种方式,一个模块可以监听他们需要监听的事件、并回应这些事件,而不需要了解系统外的其它东西甚至是否存在。

这是一个好的开始,而且这个功能同样适用于一些小应用。

事件汇集器可以通过App的属性vent调用,你可以简单地订阅或退订(译注:亦即监听与停止监听)通过on与off方法。这些方法听起来相当熟悉,因为这个事件汇集器就是扩展自Backbone的Event对象。你需要担心的唯一问题是我们正在一个任何地方都能访问到地对象上使用事件,所以所有的模块都能通过它来通信。

区域 Regions

Region是另一个Marionette的模块使得你可以轻松地绑定View到不同的HTML的区域。 我不会讲具体的Region的工作方式——那是另外一个一整天的课题——不过我会简单地说明一下并说明如何与Application协同使用它们。

一个Region是一个对象,通常通过这种方式创建:new Backbone.Marionette.Region({ el: 'selector'})——它可以管理一个你绑定了一个视图(View)的区域。你可以添加一个视图并通过show方法自动地渲染它。然后,你可以关闭这个视图(意味着移除相关的DOM节点,并且如果你用了Marionette自己的视图的话还会自动解绑所有的事件(译注:似乎Backbone的后续版本也会在相应的remove方法中自动处理所有的事件解绑)),并且通过再次调用show方法渲染一个不同的视图。Region当然可以做更复杂的事情,但事实上能通过一个方法就处理视图的渲染与关闭使这些Region非常实用。来让我们用Code说话:

// 创建一个region,它会控制#container里面的DOM var region = new Backbone.Marionette.Region({ el: "#container" }); // 添加一个视图到region里。这个视图也会立即自动渲染。 region.show(new MyView()); // 关闭现在的这个视图,并渲染显示另一个视图 region.show(new MyOtherView()); // 关闭这个视图,使得#container什么都不显示 region.close(); 

如果你想通过App直接访问某些Region(类似App.someRegion),有一个简单的方式可以直接添加:addRegions。你可以通过三种不同的方式使用addRegions,每种都会直接把Region通过参数名添加到App对象上,但每种方式使用的值都不一样,取决于你希望通过哪种方式完成这个操作:

选择器 Selector:

简单地提供选择器字符串,然后一个标准的region就会被通过传入选择器字符串到创建的新的region的el参数里:

App.addRegions({ container: "#container", footer: "#footer" }); // 等同于: App.container = new Backbone.Marionette.Region({el:"#container"}); App.footer = new Backbone.Marionette.Region({el:"#footer"}); 

自定义Region类型:

你可以继承Region来创建你自己的region类型。如果你想要用你自己的region类型, 你可以用下述的语法。注意,使用这种方式,el必须已经定义在你自己的Region类型里:

var ContainerRegion = Backbone.Marionette.Region.extend({ el: "#container", // Must be defined for this syntax // Whatever other custom stuff you want }); var FooterRegion = Backbone.Marionette.Region.extend({ el: "#footer", // Must be defined for this syntax // Whatever other custom stuff you want }); // Use these new Region types on App. App.addRegions({ container: ContainerRegion, footer: FooterRegion }); // This is equivalent to: App.container = new ContainerRegion(); App.footer = new FooterRegion(); 

自定义Region类型并使用选择器:

如果你没有定义el,或者你想要在你自己的Region类型中改写它,你可以使用这样的语法:

var ContainerRegion = Backbone.Marionette.Region.extend({}); var FooterRegion = Backbone.Marionette.Region.extend({}); // Use these new Region types on App. App.addRegions({ container: { regionType: ContainerRegion, selector: "#container" }, footer: { regionType: FooterRegion, selector: "#footer" } }); // This is equivalent to: App.container = new ContainerRegion({el:"#container"}); App.footer = new FooterRegion({el:"#footer"}); 

你可以看到,添加全局App范围的region非常的简单(尤其是使用的是标准Region类型的时候),而且它们添加了很多有用的功能。

总结

就像你见到的,Marionette添加了一堆很棒的功能使得Backbone开发变得更简单,而且我们目前还只说明了它提供的很少的模块(当然,我们已经使用了很多Application自己用到的模块,当然那些需要更多的研究)。我希望这会诱惑你渴望阅读更多的后续内容。

译者总结

总地来说Marionette提供了很多放眼整个应用框架级别的设计思路与工具,而这些是每一个复杂应用都无法绕过的,所以能减少很多重复制造的轮子。这部分的东西恰是Emberjs或Angularjs的优势,也是Backbone所没有涉及到的内容。

后续的Part 2还没翻译,看这篇文章的反响如何先吧。

感兴趣的同学也可以关注我的知乎专栏 http://zhuanlan.zhihu.com/qianduan

此文的专栏链接:http://zhuanlan.zhihu.com/qianduan/19861173


此文章转自  :http://blog.waterwu.me/marionettejs-thorough-introduce-1/

转载请注明:阿尤博客 » Marionettejs 全面介绍 (1)

游客
发表我的评论 换个身份
取消评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  • 验证码 (必填)点击刷新验证码