Marionette.Module

Marionette.Module

Marionette 模块允许你创建模块化封装的逻辑.他们可以用户将大程序分离为多个文件,构建你应用独立的组件.

文档目录

基本使用

模块定义

回调函数定义

对象字面量定义

模块类

定义子模块

开始和停止模块

开始模块

开始事件

阻止模块的Auto-Start

使用Parent开始子模块

停止模块

停止事件

模块初始器(弃用)

模块终止器(弃用)

基本使用

模块直接从Application对象定义,创建模块需要给它给它个名字.

var MyApp = new Marionette.Application();

// Creates a new module named "MyModule"
var myModule = MyApp.module("MyModule");

myModule === MyApp.MyModule; // => true

  

模块一旦创建后不能重载.用相同参数module的后续调用不会创建新的模块,而是返回已经创建的模块.

 

var MyApp = new Marionette.Application();

// Instantiates a new Marionette.Module
var myModule = MyApp.module("MyModule");

// Returns the module you just created
var theSameModule = MyApp.module("MyModule");

  

模块定义

当你实例化时你可以为你的模块提供定义.定义也可以是回调函数或对象字面量.

回调函数定义

回调函数定义将在调用module方法时立即唤醒.

接收6个参数,按顺序为:

模块自己

应用对象

Backbone

Marionette

jQuery

Underscore

任意自定义的参数

在回调中你可以直接向你的模块附加公有和私有函数和数据.

MyApp.module("MyModule", function(MyModule, MyApp, Backbone, Marionette, $, _){

  // The context of the function is also the module itself
  this === MyModule; // => true

  // Private Data And Functions
  // --------------------------

  var myData = "this is private data";

  var myFunction = function(){
    console.log(myData);
  }


  // Public Data And Functions
  // -------------------------

  MyModule.someData = "public data";

  MyModule.someFunction = function(){
    console.log(MyModule.someData);
  }
});

console.log(MyApp.MyModule.someData); //=> public data
MyApp.MyModule.someFunction(); //=> public data
  

  

额外的参数

你能在定义函数中提供额外参数,让你可以引用想要在你的模块域内的第三方库和别的资源.

在module调用自己的定义时传递传递参数.

MyApp.module("MyModule", function(MyModule, MyApp, Backbone, Marionette, $, _, Lib1, Lib2, LibEtc){

  // Lib1 === LibraryNumber1;
  // Lib2 === LibraryNumber2;
  // LibEtc === LibraryNumberEtc;

}, LibraryNumber1, LibraryNumber2, LibraryNumberEtc);

  

模块分开定义

有时模块定义很长.你可以对模块函数的连续调用来分开定义.

这可用于跨多个文件来定义你的模块.

MyApp.module("MyModule", function(MyModule){
  MyModule.definition1 = true;
});

// The following could be in a separate file
MyApp.module("MyModule", function(MyModule){
  MyModule.definition2 = true;
});

MyApp.MyModule.definition1; //=> true
MyApp.MyModule.definition2; //=> true

  

对象字面量定义

模块的字面量对象定义使得比回调方法更灵活.比如使你为你的模块指定自定义类.

通过字面量对象定义可通过define属性来设置定义函数.

MyApp.module("MyModule", {
  define: function(MyModule, MyApp, Backbone, Marionette, $, _) {
    // Define your module here
  }
});

  

指定自定义模块类

对象字面量定义的一个好处是指定自定义模块类.你可使用扩展函数创建一个新类.

当moduleClass省略时Marionette将默认实例化一个新的Marionette.Module.

var CustomModule = Marionette.Module.extend({
  // Custom module properties
});

MyApp.module("Foo", {
  moduleClass: CustomModule,
  define: function() {} // You can still use the definition function on custom modules
});

  

初始化函数

模块一个初始化函数,当Module 唤醒时立即调用.你可以将initialize函数看做构造函数的扩展.

初始化函数仅当使用模块的字面量对象定义时有效.

初始化函数和构造函数传递相同参数.

模块名称

应用

模块自己的对象字面量定义(允许你向模块传递任意值)

 

MyApp.module("Foo", {
  initialize: function( moduleName, app, options ) {
    console.log( options.someVar ); // Logs 'someString'
  },
  someVar: 'someString'
});

  

初始化函数和define函数不同.主要区别是初始化函数是在原型链上,而define不是.也就是说initialize可以被继承.

var CustomModule = Marionette.Module.extend({
  define: function() {},    // This is not inherited and will never be called
  initialize: function() {} // This, on the other hand, will be inherited
});

  

模型类

模型类可以选择性的用于定义模式

Module的extend函数和其他Backbone和Marionette的extend方法相同.允许模型生命周期事件比如onStart和onStop直接调用.

var FooModule = Marionette.Module.extend({
  startWithParent: false,

  initialize: function(options, moduleName, app) {
  },

  onStart: function(options) {
  },

  onStop: function(options) {
  },
});

MyApp.module("Foo", FooModule);

  

若模型的所有功能在它的类中定义了,类可以直接传递.MyApp.module("Foo",FooModule)

定义子模型

子模型可以通过传递逗点分割的模块列表来在一次调用中定义.

MyApp.module("Parent.Child.GrandChild");

MyApp.Parent; // => a valid module object
MyApp.Parent.Child; // => a valid module object
MyApp.Parent.Child.GrandChild; // => a valid module object

  

当使用逗点来定义子模块时,父模块可以不存在,他们会自动为你创建.如果父模块已经存在实例化,那个实例将被使用.

获取模块

虽然模块直接附加到Application实例上,我们不建议这种方式获取,而是使用.module()函数来获取.

让我们看看两种获取MyModule.Submodule模块的方式.

// Not recommended
var myModule = App.MyModule.Submodule;

// Recommended
var MyModule = App.module('MyModule.Submodule');

  

启动和停止模块

模块可以依赖应用和其他模块来启动和停止。这让它们可以异步加载,也可以在不需要时停止。

这让单元测试也容易,因为你可以在测试中仅仅启动你需要测试的模块。

启动模块

模块默认开启随着父应用同时开启。用于启动停止的模块有一个.start函数.或者模块可以配置依赖于父级的启动而启动.

例子中,模块随着父级应用对象的start方法调用而展示自动也启动的行为.

MyApp = new Marionette.Application();

MyApp.module("Foo", function(){
  // module code goes here
});

MyApp.start();

  

注意MyApp.start()调用后加载的模块将立即启动.

启动事件

当模块启动时,'before:start'事件将优先于其它运行的任何初始化器首先被触发.'start'事件然后在它们之后触发.

var mod = MyApp.module("MyMod");

mod.on("before:start", function(){
  // do stuff before the module is started
});

mod.on("start", function(){
  // do stuff after the module has been started
});

  

启动事件传递数据

.start接受单个options参数,这个参数同时传递到相关方法(onStart和onBeforeStart)上.

var mod = MyApp.module("MyMod");

mod.on("before:start", function(options){
  // do stuff before the module is started
});

mod.on("start", function(options){
  // do stuff after the module has been started
});

var options = {
 // any data
};
mod.start(options);

  阻止模块的Auto-Start

默认模块随着应用启动而启动.如果你想要手动启动模块,你可以通过startWithParent属性改变此行为.

var fooModule = MyApp.module("Foo", function(){

  // prevent starting with parent
  this.startWithParent = false;

  // ... module code goes here
});

// start the app without starting the module
MyApp.start();

// later, start the module
fooModule.start();

  

模块的字面量对象定义来定义这种行为.

var fooModule = MyApp.module("Foo", {
  startWithParent: false
});

  

当将模块跨文件分割时,建议将startWithParent设为false.

随着父级开启子模块

子模块默认随着父模块而启动.子模块按照深层优先的顺序启动.也就是说,Foo.Bar.Baz这样的层次首先启动Baz,然后Bar,最后Foo.

MyApp.module("Foo", function(){...});
MyApp.module("Foo.Bar", function(){...});

MyApp.start();

  

例子中,'Foo.Bar'模块将随着MyApp.start()方法调用启动,因为'Foo'默认随着app而启动.

子模块可以设置startWithParent为false来重载此行为.这阻止通过父级的start方法调用而启动.

现在模块'Foo'将启动,但是子模块'Foo.Bar'将不会启动.

MyApp.module("Foo", function(){...});

MyApp.module("Foo.Bar", function(){
  this.startWithParent = false;
})

MyApp.start();

  

通过上述配置子模块将使用手动启动.

MyApp.module("Foo.Bar").start();

  

 停止模块

模块可以停止或关闭,在模块不需要时来清除内存和资源.像启动模块那样,停止也是按照深度优先的层次顺序.也就是说,'Foo.Bar.Baz'的层次模块将首先停止Baz,然后Bar,最后Foo.

停止模块和孩子模块,调用模块的stop方法

MyApp.module("Foo").stop();

  

模块不会被应用自动停止.如果你想要停止比须调用自己的stop方法,或在父级模块上调用stop方法.当你停止任何父级模块时,所有的孩子模块也会被停止.

MyApp.module("Foo.Bar.Baz");

MyApp.module("Foo").stop();

  

stop方法的调用会让Bar和Baz模块同时停止,因为它们是Foo的子模块.关于定义子模块的详情,请看'定义子模块'章节.

停止事件

当停止模块时,'before:stop'事件在任何终止器前首先触发 .'stop'事件将在它们运行后触发.

var mod = MyApp.module("MyMod");

mod.on("before:stop", function(){
  // do stuff before the module is stopped
});

mod.on("stop", function(){
  // do stuff after the module has been stopped
});

  

模块Initializers

警告:弃用

这个特性已经弃用,计划在Marionette 版本3中移除.

而不是使用Initializer,你应该使用事件来管理启动过程逻辑.start事件是Initializer的理想代替品.

如果你依赖Initializer的延迟特性,你应该使用Promise来代替.这看起来像下面这样:

doAsyncThings().then(myModule.start);

  

模块,可以像Application对象那样配置成拥有initializer.就像Application的initializer这样,模块的initializer在模块启动时运行.而且,没有initializer数量的限制.

initializer可以通过模块的定义函数来添加.

MyApp.module("Foo", function(Foo){

  Foo.addInitializer(function(){
    // Do things once the module has started
  });

  Foo.addInitializer(function(){
    // You can have more than one initializer
  });

});

  

模块Finalizers

警告:弃用

这个特性已经弃用,计划在Marionette 版本3 中移除,代替使用Finalizer,你应该使用事件来管理停止逻辑.停止事件是Finalizer的理想替代.

如果你在你的app中依赖Finalizer的延迟特性,你应该使用Promise.看起来像下面这样:

doAsyncThings().then(myModule.stop);

  

模块有和initializer工作相反的finalizer:当模块通过stop方法停止时被调用.

你可以有你需要的多个finalizer

MyApp.module("Foo", function(Foo){

  Foo.addFinalizer(function(){
    // Tear down, shut down and clean up the module in here
  });

  Foo.addFinalizer(function(){
    // Do more things
  });

});

  

posted @ 2016-04-12 11:40  MonicaMiao  阅读(190)  评论(0编辑  收藏  举报