前端輕量級MVC架構CanJS詳解,mvccanjs詳解

來源:互聯網
上載者:User

前端輕量級MVC架構CanJS詳解,mvccanjs詳解

選擇正確的庫

建立一個JS APP沒有好的工具是很有難度的,jQuery只是操作DOM的庫,沒有提供任何建立APP的基礎,這就是為什麼我們要一個類似CanJS的專門的庫。

CanJS 是一個輕量級的MVC庫,提供你建立一個JS APP所需的工具。

CanJS 是一個輕量級的MVC庫,提供你建立一個JS APP所需的工具。 它提供有MVC (Model-View-Control) 模式的基本架構,模板動態綁定, route的支援且 記憶體安全。同時支援 jQuery, Zepto, Mootools, YUI, Dojo,有豐富的擴充和外掛程式。

第一部分你將學到:
建立Control控制層 和 View 視圖層(UI模板) 來顯示連絡人
用Model模型層來表示資料
使用 fixtures 外掛程式類比ajax返回資料
你肯定激動了!我們開始碼代碼吧。
建立好你的檔案夾和HTML
你先給你的APP建立一個檔案夾,目錄下再建立4個子檔案夾:css, js,views 和 img。如下:
contacts_manager
css
js
views
img

儲存以下的代碼為 index.html:

複製代碼 代碼如下:
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>CanJS Contacts Manager</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/contacts.css">
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="span12">
          <h1>Contacts Manager</h1>
        </div>
      </div>
      <div class="row">
        <div class="span3">
          <div class="well">
            <nav id="filter"></nav>
          </div>
        </div>
        <div class="span9">
          <div id="create"></div>
          <div id="contacts"></div>
        </div>
      </div>
    </div>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js"></script>
    <script src="js/can.jquery.min.js"></script>
    <script src="js/can.fixture.js"></script>
    <script src="js/contacts.js"></script>
  </body>
</html>

在頁面的底部你載入所需的JS(包括你的APP:contacts.js)。
教程中用到的CSS和圖片檔案可以下載。

用View來打造你的UI

View是用來渲染你APP的UI模板。CanJS 支援多種模板引擎,本文用EJS ,CanJS包含有而且支援動態綁定。
EJS 模板的標籤與HTML很像,支援包含JS代碼,三種常用標籤如下:
<% CODE %> 執行JS
<%= CODE %> 執行JS,並將非轉義的結果寫入當前位置的HTML
<%== CODE %>  執行JS,並將轉義的結果寫入當前位置的HTML(用於子模板).
模板可以從檔案或者script標籤中載入得到,本教程從 EJS 檔案載入。

顯示連絡人

要建立連絡人,你得先建立一個EJS 模板,儲存以下代碼為contactsList.ejs 進你的views 檔案夾:

複製代碼 代碼如下:
<ul class="clearfix">
  <% list(contacts, function(contact){ %>
    <li class="contact span8" <%= (el)-> el.data('contact', contact) %>>
      <%== can.view.render('views/contactView.ejs', {
        contact: contact, categories: categories
      }) %>
    </li>
  <% }) %>
</ul>

contactLists.ejs 會渲染一個連絡人清單,我們分析一下此模板:

複製代碼 代碼如下:
<% list(contacts, function(contact){ %>

list()方法裡的回調方法如果配合配置有觀察者的list使用時,一旦list的資料發生改變就運用動態綁定重複調用。

複製代碼 代碼如下:
<li class="contact span8" <%= (el)-> el.data('contact', contact) %>>

以上代碼通過元素的回調方法產生 一個有連絡人資料的<li>。 箭頭後的方法執行後將el對象的資料設定給對應的元素。

複製代碼 代碼如下:
<%== can.view.render('views/contactView.ejs', {
  contact: contact, categories: categories
}) %>

以上代碼將子模板contactView.ejs 渲染成一個連絡人。 can.view.render() 以模板和資料為參數返回HTML。

渲染單個連絡人

子模板是一個將view組織成可管理塊的好辦法。 同時也使你的模板簡單和易於重用。教程後面將會用到此模板來建立連絡人,將下面的代碼儲存為contactView.ejs 進 views 檔案夾:

複製代碼 代碼如下:
<a href="javascript://" class="remove"><i class="icon-remove"></i></a>
<form>
<div class="row">
  <div class="span2">
    <img src="img/contact.png" width="100" height="100">
  </div>
  <div class="span3">
    <input type="text" name="name" placeholder="Add Name"
      <%= contact.attr('name') ? "value='" + contact.name + "'" : "class='empty'" %>>
    <select name="category">
      <% $.each(categories, function(i, category){ %>
        <option value="<%= category.data %>" <%= contact.category === category.data ? "selected" : "" %>>
          <%= category.name %>
        </option>
      <% }) %>
    </select>
  </div>
  <div class="span3">
    <label>Address</label>
    <input type="text" name="address"
      <%= contact.attr('address') ? "value='" + contact.address + "'" : "class='empty'" %>>
    <label>Phone</label>
    <input type="text" name="phone"
      <%= contact.attr('phone') ? "value='" + contact.phone + "'" : "class='empty'" %>>
    <label>Email</label>
    <input type="text" name="email"
      <%= contact.attr('email') ? "value='" + contact.email + "'" : "class='empty'" %>>
  </div>
</div>
</form>

連絡人的屬性都放入了 <input> 標籤裡,這就可以編輯更新使用者的資料。

活化你的View(好文藝。。)

EJS 處理模板過程中如果有用到attr() ,它周圍的代碼將會交由事件處理器管理,監聽對應屬性的變化,當屬性發生變化,APP中關聯的UI將會被更新。這功能利益於模板動態綁定機制,EJS的動態綁定是有選擇性的,只有使用了attr()時才會為對應的屬性開啟。
我們通過 contactView.ejs 中一個<input>標籤來瞭解它的用法:

複製代碼 代碼如下:
<input type="text" name="name" placeholder="Add Name"
  <%= contact.attr('name') ? "value='" + contact.name + "'" : "class='empty'" %>>

特殊標記裡的代碼將轉變成事件綁定到此連絡人的name屬性上。當name屬性發生變化,事件將被觸發同時HTML結構會被更新。

使用can.Control來處理商務邏輯

can.Control 建立了一個可組織,內在無泄漏,全權控制器,能用來建立widget或者處理商務邏輯。你通過所需要資料為一個DOM元素建立一個Control執行個體,可以在你的Control中定義方法綁定事件。
當 Control 所關聯的元素從DOM被刪除時,Contol會自去銷毀自己,同時清除所綁定的方法。
要建立一個 Control,通過傳入你定義的包含有函數的對象給 can.Control() 來實現繼承。接下來事件也給傳進去了。
每個Contol執行個體都有幾個重要的值和方法規範:
this –  Control 執行個體的引用
this.element – 執行個體中你所建立的DOM 元素
this.options – 建立執行個體所需要的參數對象
init() – 當執行個體建立成功時被調用

管理連絡人

將以下程式碼片段添加到contacts.js 檔案來建立管理連絡人的Control:

複製代碼 代碼如下:
Contacts = can.Control({
  init: function(){
    this.element.html(can.view('views/contactsList.ejs', {
      contacts: this.options.contacts,
      categories: this.options.categories
    }));
  }
})

當 Contacts 的執行個體被建立時, init() 會做兩件事:
使用can.view() 來渲染連絡人。 can.view() 接收兩個參數:包含有模板和資料的檔案或者stript標籤;將返回一個documentFragment (一個管理DOM元素的輕量容器)。
使用jQuery.html()將can.view() 的documentFragment 插入Control的元素

使用Model來表現資料

Model 是APP資料的抽象層。本APP用到兩個Model:一個對應連絡人,一個對應類別。將以下代碼添加到contacts.js:

複製代碼 代碼如下:
Contact = can.Model({
  findAll: 'GET /contacts',
  create  : "POST /contacts",
  update  : "PUT /contacts/{id}",
  destroy : "DELETE /contacts/{id}"
},{});
 
Category = can.Model({
  findAll: 'GET /categories'
},{});

一個model 有5個方法可能定義來CRUD資料, 分別是findAll, findOne, create, update 和 destroy。你可重寫這幾個方法,不過最好的辦法是使用 REST 服務(Representational State Transfer具象狀態傳輸)。正如上面的代碼,你放心的忽略APP中不會用到的靜態方法了。

這裡要重點指出的是,model執行個體其實是源自 CanJS 的‘observables'。can.Observe 提供對象的觀察者模式can.Observe.List 提供數組的觀察模式。這意味著你可以通過attr()來get和set資料,同時監聽資料的變動。
findAll() 方法返回一個 Model.list,就是當元素被添加或者移除時 can.Observe.List 所觸發的事件。

使用Fixture來模仿Rest

Fixture攔截 AJAX 請求並通過檔案或者方法來類比應答。這對測試,或者後端還沒有就緒時是非常有用的。Fixture就是APP的model類比REST所需要的。
首先,你要準備一些資料給fixture,添加以下代碼到:

複製代碼 代碼如下:
var CONTACTS = [
  {
    id: 1,
    name: 'William',
    address: '1 CanJS Way',
    email: 'william@husker.com',
    phone: '0123456789',
    category: 'co-workers'
  },
  {
    id: 2,
    name: 'Laura',
    address: '1 CanJS Way',
    email: 'laura@starbuck.com',
    phone: '0123456789',
    category: 'friends'
  },
  {
    id: 3,
    name: 'Lee',
    address: '1 CanJS Way',
    email: 'lee@apollo.com',
    phone: '0123456789',
    category: 'family'
  }
];
 
var CATEGORIES = [
  {
    id: 1,
    name: 'Family',
    data: 'family'
  },
  {
    id: 2,
    name: 'Friends',
    data: 'friends'
  },
  {
    id: 3,
    name: 'Co-workers',
    data: 'co-workers'
  }
];

有了資料,要將其串連到fixture來類比REST 。can.fixture()接收兩個參數。 我們要攔截的URL和我們應答用的檔案和方法。通常你要攔截的URL都是動態且遵循一個模式的。在需要在URL裡添加以{}括起的萬用字元即可。

添加以下代碼到contacts.js:

複製代碼 代碼如下:
can.fixture('GET /contacts', function(){
return [CONTACTS];
});
 
var id= 4;
can.fixture("POST /contacts", function(){
return {id: (id++)}
});
 
can.fixture("PUT /contacts/{id}", function(){
return {};
});
 
can.fixture("DELETE /contacts/{id}", function(){
return {};
});
 
can.fixture('GET /categories', function(){
return [CATEGORIES];
});

前4個 fixture類比 Contact model的GET, POST, PUT 和 DELETE 應答,第5個類比 Category model的GET應答。

啟動APP

你的APP有管理資料的Model,渲染連絡人的 View,將這一切組織起來的的Control。現在要做的就是啟動APP了。 Now you need to kickstart the application!
將以下代碼添加到contacts.js :

複製代碼 代碼如下:
$(document).ready(function(){
  $.when(Category.findAll(), Contact.findAll()).then(
    function(categoryResponse, contactResponse){
      var categories = categoryResponse[0],
        contacts = contactResponse[0];
 
      new Contacts('#contacts', {
        contacts: contacts,
        categories: categories
      });
  });
});

我們來分析一下這段代碼:

複製代碼 代碼如下:
$(document).ready(function(){

使用 jQuery.ready 方法監聽DOM的ready。

複製代碼 代碼如下:
$.when(Category.findAll(), Contact.findAll()).then(
  function(categoryResponse, contactResponse){

調用兩個Model的 findAll() 方法來擷取全部連絡人的類型,由於findAll() 有延時, $.when()則確保兩個請求同時完成後才執行回調方法。

複製代碼 代碼如下:
var categories = categoryResponse[0],
  contacts = contactResponse[0];

從兩個 findAll() 方法中擷取對應Model執行個體的資料集。 是應答所返回的數組的第一個元素。

複製代碼 代碼如下:
new Contacts('#contacts', {
  contacts: contacts,
  categories: categories
});

為 #contacts 元素建立Contact 的Control 。連絡人和類型資料集傳進Control。
用瀏覽器開啟你的APP,你將看到如下的連絡人清單:

總結

這是第教程系列的第一篇,你已經瞭解了CanJS的核心:
Models 你的APP資料的抽象層
Views 將資料轉換成HTML的模板
Controls 組織關聯一切


有沒有不用“前端模板”技術的前端(js)MVC架構?

當然用模板方便啊
你難道想一個個去寫innerHTML?
 
aspnet mvc架構優缺點

MVC優點:
1.大型開發的時候容易維護,擴充性很好。
2.能夠對HTML有完全的控制許可權,對於前端來說很友好。
3.能夠進行單元測試,保證功能的實現。

缺點:
1.沒有那麼多的現成控制項使用,開發效率相對較低(特別是對於菜鳥來說)
2.對於大型資料的處理比較難,還是因為沒有現成girdview控制項。這個控制項雖然產生的html結構異常複雜,但是對於處理大量而且複雜的資料來說是很不錯的。不過一般網站是很少有這種大量且複雜的資料,很多菜鳥都是用這個大炮來打蚊子,浪費且低效率。對於網站開發來說這個控制項應該不推薦使用。

剛學的菜鳥和在需要快速開發的情況下用webform就很好。
需要可擴充性,高度控制性情況下用MVC好。但是用這個架構門檻相對較高,如果你只懂asp.net 的webform開發形式的話,因為webform已經幫你做了太多的事情,換句話說你根本不知道真正的web開發是怎麼樣的。反而精通php,asp的人更容易上手。

MVC和webform開發各有各的用途。
但是你不應該使用asp.net mvc架構,如果符合下面幾條:
你對多態不是“非常”的熟悉
你不喜歡在這個架構上構建應用程式
你依賴於很多第三方的UI控制項
你不喜歡使用開源的程式
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.