2014-03-08_javascrit_controller&status

模块模式:

模块模式是用来封装逻辑并避免命名空间污染的好方法。使用匿名函数可以做到这一点,通常是创建一个匿名函数并立即执行它。在匿名函数中的逻辑都在闭包里运行,为应用中的变量提供了局部作用域和私有的运行环境:

(function(){

/* ... */

})();

在执行这个匿名函数之前,我们用一对括号()将它包起来。这样才能让javascirpt解释器正确地将这段代码解释为一个语句。

全局导入:

定义在模块里的变量都是局部变量,因此在全局命名空间中是无法访问他们的。然而应用的全局变量仍是可用的,从模块的内部可用很容易的访问并操纵它们。开发者往往很难一眼看出哪个全局变量被模块使用了,尤其是当模块数量很多的时候。

 

另外,隐式的全局变量会让程序变的更慢,因为javascript解释器不得不遍历作用域链。

 

将全局对象作为参数传入匿名函数,可以导入我们的代码中,这种实现比隐式的全局对象更加简洁高效。

(function($){

/* ...*/

})(jQuery);

这个例子我们将全局对象jQuery导入我们的模块里,并将其重命名$。它清晰的表明这个模块中所用到的全局变量是什么,并且对这个全局对象的读取速度更快。

全局导出:

(function($,exports){

exports.Foo="wem";

})(jQuery,window);

assertEqual(Foo,"wem");

这里我们使用的变量名叫exports,用它来暴露全局变量,这样代码看起来干净易读,可以直接看出模块创建了哪些全局变量。

添加少量上下文

使用局部上下文是一种架构模块很有用的方法,特别是当需要给事件注册回调函数时。实际情况是,模块中的上下文都是全局的,this就是window

(function(){

    assertEqual(this,window);

})();

如果想自定义作用域的上下文,则需要将函数添加至一个对象中,比如:

(funcion(){

    var mod={};

    mod.contextFunction=function(){

        assertEqual(this,mod);

    };

     mod.contextFunction();

})();

在 mod.contextFunction()中上下文不是全局的,而是mod对象。这时使用this就不用担心创建全局变量了。

(funcion($){

    var mod={};

    mod.load=function(func){

        $($.proxy(func,this));

    };

    mod.load(function(){

        this.view=$("#view");

    });

    mod.assetsClick=function(){

        //处理点击

    };

    mod.load(funtion(){

        this.view.find(".assets").click($.proxy(this.assetsClick,this));

    });

})(jQuery);

这里创建了新的load()函数来处理回调,当页面加载后执行它,我们使用了jQuery的proxy()来确保回调函数是基于正确的上下文执行的

抽象出类库
(function($,exports){
 var mod=function(includes){
  if(includes)this.include(includes);
 };
 mod.fn=mod.prototype;
 mod.fn.proxy=function(func){
  return $.proxy(func,this);
 };
 mod.fn.load=function(func){
  $(this.proxy(func));
 };
 mod.fn.include=function(ob){
  $.extend(this,ob);
 };
 exports.Controller=mod;

})(jQuery,window);

proxy()保证了函数在局部上下文中执行,对于事件回调来说是非常有用的模式。
include()函数只是给控制器添加属性、保存类型功能的快捷方式。
代码中将控制器挂载到export对象中,对外暴露为全局的Controller变量

例子:根据鼠标是否移过元素来给它添加和删除一个元素的类
(function($,Controller){
 var mod=new Controller;
 mod.toggleClass=function(){
     this.view.toggleClass("over",e.data)
 };
 mod.load(function(){
   this.view=$("#view");
   this.view.mouseover(this.proxy(this.toggleClass),true);
   this.view.mouseout(this.proxy(this.toggleClass),false);
  }
 );

})(jQuery,Controller)

 

文档加载完后载入控制器

//使用全局对象作为上下文而不是window对象

//用来创建全局对象

var exports=this;

(function(){
 var mod={};
 mod.create=function(includes){
  var result=function(){
   this.init.apply(this,argument);
  };
  result.fn=result.prototype;
  result.fn.init=function(){};
  result.proxy=function(func){return $.proxy(func,this);};
  result.fn.proxy=result.proxy;
  result.include=function(obj){$.extend(result.fn,obj);};
  result.extend=function(obj){$.extend(result,obj);};
  if(includes)result.include(includes);
  return result;
 };
 exports.Controller=mod;
})(jQuery);

 

 现在我们可以使用新的Controller.create()函数来创建控制器,传入一个包含实例属性的对象直接量
注意这里整个控制器都被包装在jQuery(function(){/* ... */})中,这是jQuery.ready()的另一种写法,
这句话的意思就是在页面DOM节点构建完成后才执行初始化的动作加载控制器。
jQuery(function($){
  var ToggleView = Controller.create({
    init: function(view){
      this.view = $(view);
      this.view.mouseover(this.proxy(this.toggleClass), true);
      this.view.mouseout(this.proxy(this.toggleClass), false);        
    },
    this.toggleClass: function(e){
      this.view.toggleClass("over", e.data);          
    }
  });
  // Instantiate controller, calling init()
  new ToggleView("#view");
});

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章