javascriptMVC教程 — 10.開始使用jQueryMX–Controller

來源:互聯網
上載者:User

  JavaScriptMVC的 controllers 可以做什麼事情,他是一個jquery外掛程式工廠。他們可以被當成傳統視圖使用,製作分頁控制項或者grid,也可以把他們當成傳統的控制器使用,初始化控制器並把他們和model結合。Controller對組織應用程式相當有協助。

  Controller提供了很多相當有用的特性,例如:

  • jQuery 外掛程式建立
  • 自動綁定
  • 預設設定
  • 自動決定

  下面的代碼建立了一個tooltip控制項,當頁面被點擊的時候元素將會顯示:

$.fn.tooltip = function(){  var el = this[0];  $(document).click(function(ev){    if(ev.target !== el){      $(el).remove()    }  })  $(el).show();  return this;})

  要使用這個控制項,你需要在頁面上添加一個元素,然後在他上面使用tooltip:

$("<div class='tooltip'>Some Info</div>")    .appendTo(document.body)    .tooltip()

  但是上面的代碼存在問題,那就是會有很多tooltip元素會被建立,他們會被儲存在記憶體中佔用很多內容,這會導致效能問題。這是因為click的處理函數不會從頁面中移除,會有個閉包一直指向這些元素。

  而且這也很容易造成錯誤。當html元素從頁面上移出的時候,jquery會移出他相關的事件處理,所以開發人員不用擔心取消事件綁定。但是對於元素之外的事件處理,例如document上的,並沒有取消事件綁定。在MVC架構中,Controller監聽View,View監聽Model。你會一直監聽控制項元素外面的事件,例如之前章節中講到的nextPrev外掛程式,會監聽paginate模型的更新操作。

paginate.bind('updated.attr', function(){  self.find('.prev')[this.canPrev() ? 'addClass' : 'removeClass']('enabled')  self.find('.next')[this.canNext() ? 'addClass' : 'removeClass']('enabled');})

  但是他們並不從paginate中取消綁定,忘記刪除事件處理常式是一個潛在的錯誤的來源。然而tooltip 和 nextPrev都不會發生錯誤,但是他們會默默的消耗應用程式的效能。幸運的是,$.Controller讓工作邊的簡單而易管理,我們可以像下面這樣重寫tooltip:

$.Controller('Tooltip',{  init: function(){    this.element.show()  },  "{document} click": function(el, ev){    if(ev.target !== this.element[0]){      this.element.remove()    }  }})

  當document被點擊或者元素從DOM移出,$.Controller會自動取消對document click事件的綁定。$.Controller也綁定nextPrev控制項的paginate模型:

$.Controller('Nextprev',{  ".next click" : function(){    var paginate = this.options.paginate;    paginate.attr('offset', paginate.offset+paginate.limit);  },  ".prev click" : function(){    var paginate = this.options.paginate;    paginate.attr('offset', paginate.offset-paginate.limit );  },  "{paginate} updated.attr" : function(ev, paginate){    this.find('.prev')[paginate.canPrev() ? 'addClass' : 'removeClass']('enabled')    this.find('.next')[paginate.canNext() ? 'addClass' : 'removeClass']('enabled');  }})// 建立nextprev$('#pagebuttons').nextprev({ paginate: new Paginate() })

  如果#pagebuttons從頁面中移出,Nextprev控制項執行個體會自動取消對paginate模型的綁定。接下來我們討論$.Controller時如何工作的。

 

  概述

  $.Controller繼承自$.Class,使用$.Controller( NAME, classProperties, instanceProperties )去建立Controller類,參數包括控制項名稱,靜態方法和執行個體方法。下面我們開始建立一個可以重用的List控制項:

$.Controller("List", {  defaults : {}},{  init : function(){  },  "li click" : function(){  }})

  當一個controller類被建立的時候,他就建立了一個和類名字類似的jquery輔助方法。輔助方法主要用於在頁面上的html元素建立controller的執行個體。輔助方法的名字會用底線代替類名中的部分字元,例如$.Controller('App.FooBar')的輔助方法名是$(el).appfoobar()。

 

  控制器執行個體化

  可以使用new Controller(element, options)建立controller的執行個體,方法包含兩個參數:使用控制項的html元素和可選配置項,例如:

new List($('ul#tasks'), {model : Task});

  當然你也可以使用jquery輔助方法建立類的執行個體:

$('ul#tasks').list({model : Task})

  當controller執行個體被建立的時候,會調用到原型方法init:

  • this.element 指向controller所在的html元素;
  • this.options 將傳遞給建構函式的options和預設的options合并。

下面的代碼從model擷取task的資料用以更新控制器,並且使用options的模板渲染頁面:

$.Controller("List", {  defaults : {    template: "items.ejs"  }},{  init : function(){    this.element.html( this.options.template, this.options.model.findAll() );   },  "li click" : function(){  }})

我們可以像這樣使用List控制器,代碼相當的簡單,如果我們不提供模板,List會預設使用"items.ejs"。

$('#tasks').list({model: Task, template: "tasks.ejs"});$('#users').list({model: User, template: "users.ejs"})

 

  事件綁定

  $.Controller一個強大的特性是對事件的綁定和取消綁定。當controller被建立的時候,他會查詢action方法。action方法看起來像事件處理方法,例如"li click"。那些action使用jQuery.bind 或者jQuery.delegate實現綁定。當controller被銷毀的時候,controller所在的html元素會從頁面中移出,或者使用controller的destroy方法,那些事件會取消綁定,以節約記憶體。那面是action的例子,描述了他們監聽什麼對象:

  • "li click" - controller所在元素中的li或li內部元素被click。
  • "mousemove" - controller所在元素執行mousemoves。
  • "{window} click" - window或內部對象被click。

action方法會被所在的html元素或者發生事件的對象回調,例如:

"li click": function( el, ev ) {  assertEqual(el[0].nodeName, "li" )  assertEqual(ev.type, "click")}

 

  action模板化

  $.Controller支援action模板化,可以用來綁定其他對象、自訂事件或者自訂選取器。$.Controller使用options的值或者window來代替action,例如下面的例子:

$.Controller("Menu",{  "li {openEvent}" : function(){    // 事件處理  }});//建立 menu,設定li的click事件$("#clickMenu").menu({openEvent: 'click'});//建立 menu,設定li的mouseenter事件$("#hoverMenu").menu({openEvent: 'mouseenter'});

我們可以進一步對元素的標籤實現自訂的功能:

$.Controller("Menu",{  defaults : {menuTag : "li"}},{  "{menuTag} {openEvent}" : function(){    // 事件處理}});
$("#divMenu").menu({menuTag : "div", openEvent: 'click'})

  action模板化允許你對controller之外的元素或者對象進行綁定。例如之前章節中的Task模型,他建立的過程中會觸發“created”事件。我們可以為List添加對Task created 事件的監聽,如下:

$.Controller("List", {  defaults : {    template: "items.ejs"  }},{  init : function(){    this.element.html( this.options.template, this.options.model.findAll() );   },  "{Task} created" : function(Task, ev, newTask){    this.element.append(this.options.template, [newTask])  }})

  我們也可以把model模型化,這樣可以通過在options中設定model,實現對任意model的支援:

$.Controller("List", {  defaults : {    template: "items.ejs",    model: null  }},{  init : function(){    this.element.html( this.options.template, this.options.model.findAll() );   },  "{model} created" : function(Model, ev, newItem){    this.element.append(this.options.template, [newItem])  }});// 建立 tasks list$('#tasks').list({model: Task, template: "tasks.ejs"});

 

  集合所有功能--一個抽象的CRUD列表

  現在我們為List添加對update和destroyed的支援:

"{model} updated" : function(Model, ev, updatedItem){  // 使用updatedItem更新 LI},"{model} destroyed" : function(Model, ev, destroyedItem){  // 使用destroyedItem移出 LI}

  我們會發現一個問題,需要需要找到代表特定model執行個體的元素,因此我們需要把元素標記為某個mode執行個體所有。幸運的是,$.Model 和 $.View讓上述的工作變得簡單。在ejs視圖中使用model執行個體標記元素,你只需要簡單的把model執行個體寫給元素。

<% for(var i =0 ; i < this.length; i++){ %>  <% var task = this[i]; %>  <li <%= task %> > <%= task.name %> </li><% } %>

  tasks.ejs遍曆task列表,為每一個task建立一個li,同時使用 <li <%= task %> >為task到元素的jquery資料中。可以使用modelInstance.elements([CONTEXT]),稍後通過model執行個體獲得代表他的html元素。

$.Controller("List", {  defaults : {    template: "items.ejs",    model: null  }},{  init : function(){    this.element.html( this.options.template, this.options.model.findAll() );   },  "{model} created" : function(Model, ev, newItem){    this.element.append(this.options.template, [newItem])  },  "{model} updated" : function(Model, ev, updatedItem){    updatedItem.elements(this.element)      .replaceWith(this.options.template, [updatedItem])  },  "{model} destroyed" : function(Model, ev, destroyedItem){    destroyedItem.elements(this.element)      .remove()  }});// 建立tasks list$('#tasks').list({model: Task, template: "tasks.ejs"});

  通過上面的介紹,你一定掌握了如何使用JavaScriptMVC建立抽象的、重用的和節省記憶體的外掛程式了。

 

javascriptMVC教程目錄

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.