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");
});

 

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