轉:Durandal快速入門

Durandal是一個輕量級的JavaScript框架,其目標是單頁面應用(SPAs)的開發變得簡單而優雅。它支持MVC、MVP和MVVM等模式,所以不論你採用哪一種類型的前端架構,Durandal都能勝任。css

Durandal以RequireJS爲基礎,加上一個輕量級的慣例層,帶來了使人驚歎的生產效率,而且幫助你維持穩健的編碼實踐。配上開箱即用的富界面組件、模態對話框、事件/消息、組件、過渡效果、導航等等,使你能夠輕鬆開發出任何你能想象的應用。html

儘管Durandal才發佈大約一年時間,但其社區正以飛快的速度成長。前端

所以,咱們推出了一個Kickstarter來幫助咱們在2014年完成一些神奇的事情,但願你能關注。但如今,我將向你展現如何開發一個簡單的Durandal程序。jquery

要開始使用Durandal,能夠有多種方式,這取決於你的平臺。由於Durandal是一個純JavaScript庫,獨立於任何服務端平臺,咱們嘗試用多種方式來打包,以知足各種Web開發人員。在本教程中,咱們將直接使用HTML Starter Kit。你能夠在官方網站上直接下載shell

下載完HTML Starter Kit後,解壓縮,你就能夠直接在Firefox各版本中打開index.html頁面,運行其示例程序了。或者你也能夠將其部署到Web服務器中,瀏覽其index頁面。編程

 

Starter Kit演示了一個基本的導航架構,包括導航、頁面歷史、數據綁定、模態對話框等等。固然,咱們不僅是看看而已,咱們要從頭開始寫一個小程序。首先打開app文件夾,刪除裏面的全部內容,而後刪除index.html。這樣咱們就有了一個空項目,而且預配置了全部必須的scripts和css。json

*注:IE, ChromeSafari可能沒法從文件系統中直接打開這類文件。若是你仍但願使用這些瀏覽器,能夠將其部署到你喜歡的Web服務器中。bootstrap

Index.html
咱們開始編寫index.html文件,內容以下:小程序

<!DOCTYPE html> 
<html> 
  <head> 
    <link rel="stylesheet" href="lib/bootstrap/css/bootstrap.css" /> 
    <link rel="stylesheet" href="lib/font-awesome/css/font-awesome.css" /> 
    <link rel="stylesheet" href="lib/durandal/css/durandal.css" /> 
    <link rel="stylesheet" href="css/starterkit.css" /> 
  </head> 
  <body> 
    <div id="applicationHost"></div> 
    <script src="lib/require/require.js" data-main="app/main"></script> 
  </body> 
</html>

咱們看到,文件中只有一些css樣式文件,一個id爲applicationHost的簡單的div, ,一個script標籤。咱們加上了BootstrapFontAwesome,使界面看起來美觀一些,但它們並非Durandal所必須的。咱們要關注的關鍵代碼是script標籤。api

Durandal採用RequireJS做爲其核心構件之一,鼓勵模塊化的編程方式。在Durandal應用中,全部的JS代碼都寫在模塊中。上文index.html中的script標籤就是用於加載RequireJS來完成框架的模塊策略。當模塊加載器完成初始化後,它經過data-main屬性的值來啓動應用。就像C語言中的main函數同樣,data-main屬性指向的是主模塊,是整個應用的入口。讓咱們進行下一步,建立這個模塊。首先建立一個名爲main.js的文件,把它放到app文件夾下。其代碼以下:

main.js 
requirejs.config({ 
  paths: { 
    'text': '../lib/require/text', 
    'durandal':'../lib/durandal/js', 
    'plugins' : '../lib/durandal/js/plugins', 
    'transitions' : '../lib/durandal/js/transitions', 
    'knockout': '../lib/knockout/knockout-2.3.0', 
    'jquery': '../lib/jquery/jquery-1.9.1' 
    }  
}); 
define(function (require) { 
   var system = require('durandal/system'), 
       app = require('durandal/app'); 
   system.debug(true); 
   app.title = 'Durandal Starter Kit'; 
   app.configurePlugins({ 
     router:true, 
     dialog: true 
   }); 
   app.start().then(function() { 
     app.setRoot('shell'); 
   }); 
});

這是一個很是標準的Durandal應用的樣板配置。咱們詳細地看一下代碼。

文件的最上面是requirejs.config代碼。這部分代碼用於配置模塊系統,使其可以找到核心庫。配置的都是一些相對路徑,所以當咱們引用「jQuery」時,模塊系統就知道到哪裏去加載它。咱們能夠看到,路徑的配置包括requirejs的text插件(用於加載視圖)、Durandal的核心模塊、Knockout和jQuery。Durandal採用RequireJS來構建模塊,Knockout用於數據綁定,而jQuery用於瀏覽器層的抽象。

完成RequireJS的配置後,定義應用的主模塊。Durandal應用的全部代碼都寫在模塊中,而且按照如下格式:

define(function (require) { 
  var someModule = require('some/module'); 
  ...other modules required here... 
  return someValue; 
});

咱們用define函數來建立一個模塊。它的參數是另外一個函數,這個函數是模塊的工廠。也就是說,這個函數的返回值將是模塊的一個實例。當函數返回一個對象時,你能夠建立單例對象模塊。或者返回一個函數,你能夠建立一個類構造器模塊。另外,你也能夠聲明該模塊依賴於其餘模塊,此時你須要使用require函數來引入其餘模塊。

在上面的主模塊代碼中,你能夠看到咱們引入或者說require了兩個Durandal模塊:systemapp。而後經過system模塊開啓框架的調試功能,經過app模塊設置應用的標題,加載兩個可選的插件。最後,咱們調用start方法啓動應用。該方法是一個異步的動做,當它結束時,調用一個特殊的方法:setRoot

setRoot方法被調用時,纔會真正去展現頁面。你能夠將root視爲應用的主窗口、主佈局或者應用的shell。該方法的參數指向一個包含shell的行爲的模塊。如今惟一的問題是,嗯,它還不存在。好吧,咱們開始建立它。

Shell

Durandal的大部組件都同時包含行爲(behavior)和展示(presentation)。你的應用的shell毫無疑問也遵循這個規則。咱們將經過兩個文件來展現這兩個不一樣的概念:一個是用於行爲的JavaScript文件,另外一個是用於展示的HTML文件。在app文件夾下建立:shell.jsshell.html兩個文件的代碼以下所示,咱們來看看它們是如何工做的。

shell.js 
define(function (require) { 
  var app = require('durandal/app'), 
      ko = require('knockout'); 
  return { 
     name: ko.observable(), 
     sayHello: function() { 
       app.showMessage('Hello ' + this.name() + '! Nice to meet you.',
 'Greetings'); 
     } 
   }; 
}); 
shell.html 
<section> 
  <h2>Hello! What is your name?</h2> 
  <form class="form-inline"> 
    <fieldset> 
       <label>Name</label> 
       <input type="text" data-bind="value: name, valueUpdate:
 'afterkeydown'"/> 
       <button type="submit" class="btn" data-bind="click: sayHello, enable: 
name">Click Me</button> 
    </fieldset> 
  </form> 
</section>

首先看看shell.js,正如咱們以前講到的,它定義了一個模塊。同時它還依賴兩個別的模塊:appknockout。從代碼能夠看出,模塊返回了一個對象。這個對象有一個name屬性和一個sayHello方法。屬性name看起來有點特別,它是咱們使用Knockout建立的一個可被觀察的(observable)屬性。可被觀察的(observable)屬性支持數據到html的雙向綁定,變動通知和一些其它特性。注意看sayHello中調用了app模塊的方法來顯示一個包含name屬性值的消息對話框。

要徹底理解這些代碼,你應該將它與HTML代碼放到一塊兒來看。注意觀察HTML中的data-bind屬性。該屬性將HTML與模塊中的屬性和方法聯繫起來。例如input標籤經過data-bind屬性將它的值與name屬性鏈接起來的。它同時還指定,當key down事件發生時,屬性name的值將被更新(若是不指定事件,則默認光標離開時會進行更新)。一樣地,按鈕的click事件綁定了sayHello方法,並且僅當name屬性的值爲真時,按鈕纔是有效狀態。看起來是否是很酷?如今就把應用運行起來,你能夠用Firefox打開index.html,或者若是你使用其餘瀏覽器的話,能夠部署到Web服務器下而後瀏覽index.html。當頁面打開時,會經歷如下這些步驟:

  1. 加載RequireJS。
  2. RequireJS將加載main.js,而後配置框架。
  3. main.js調用setRoot展現整個應用。
  4. 加載shell.jsshell.html,綁定數據,而後注入到頁面的applicationHost div中。

當頁面加載完成後,在輸入框中試着輸入一些內容,觀察按鈕的有效性是如何變化的,而後點擊按鈕看看發生了什麼。

導航

上面的例子看起來不錯,但大多數應用都不僅有一頁。因此,咱們開始下一步,將它擴展成具備頁面導航的應用。首先,把shell.js更名爲home.jsshell.html更名爲home.html。而後建立兩個新文件shell.jshome.js用於導航。如下是兩個新文件的代碼:

shell.js 
define(function (require) { 
  var router = require('plugins/router'); 
   
  return { 
     router: router, 
     activate: function () { 
       router.map([ 
         { route: '', title:'Home', moduleId: 'home', nav: true } 
       ]).buildNavigationModel(); 
       return router.activate(); 
     } 
   }; 
}); 
shell.html 
<div> 
 <div class="navbar navbar-fixed-top"> 
  <div class="navbar-inner"> 
   <ul class="nav" data-bind="foreach: router.navigationModel"> 
    <li data-bind="css: { active: isActive }"> 
     <a data-bind="attr: { href: hash }, html: title"></a> 
    </li> 
   </ul> 
   <div class="loader pull-right" data-bind="css: { active: 
router.isNavigating }"> 
     <i class="icon-spinner icon-2x icon-spin"></i> 
   </div> 
  </div> 
 </div> 
 <div class="container-fluid page-host" data-bind="router: { 
transition:'entrance' }"></div> 
</div>

能夠看到,shell.js仍然是模塊的標準定義方式。首先require了一個router插件,利用它建立對象。咱們配置了一個route指向home模塊。router配置中指定了每一個route匹配的模式、顯示的標題、對應加載的moduleId,以及route匹配時,是否應該將此route顯示到導航欄中(nav:true)。配置完成後,調用buildNavigationModel。該方法利用route信息,構建一個特殊的集合,這個集合經過數據綁定,能夠用來顯示頁面頂部的導航欄。最後,咱們激活這個router。全部這些都發生在activate方法中。每次Durandal向屏幕展示一個組件時,它都會查找可選的activate回調方法。若是找到,就會在數據綁定前調用此方法。所以這種方式容許你執行自定義的激活代碼,例如上面的例子在activate方法中配置應用程序的router。

若是把模塊和視圖的代碼放到一塊兒,此次你應該很容易理解它們是如何工做的了。首先綁定navigationModel屬性,生成一個導航欄navbar。每個可導航的route被轉換成一個li標籤,其中包含一個連接。連接的標題對應title,地址對應hash。同時,在navbar中還包含了一個spinner動畫圖標,並將其與router.isNavigating屬性進行綁定。當應用從一個頁面導航到另外一頁面時,咱們就能看到一個spinner動畫圖標。

在html文件的最下方有一個特殊的router綁定,也就是鏈接模塊中的router。它扮演佔位符的角色,用於顯示當前頁面。屬性transition表示當頁面發生變化時,Durandal要使用「entrance」過渡動畫。

如今將它運行起來。它看起來跟以前差很少,除了在頂端多了個導航欄。由於如今仍然只有一個頁面,所以沒有什麼使人印象深入的東西。咱們開始建立第二個頁面,以便可以在頁面間前進或後退。

第二頁:雷尼爾峯

咱們建立的第二個頁面將調用Flickr,獲取一組雷尼爾峯的照片並進行展現。首先修改shell的router配置,增長另外一個route,這樣它就有了兩個route:

{ route:'', title:'Home', moduleId:'home', nav:true }, 
{ route:'rainier', title:'Mount Rainier', moduleId:'rainier', nav:true }

第一個是咱們以前的home route,第二個是新的route用於即將建立的新頁面。這時候,但願你已經知道應該怎麼作了。咱們爲新頁面建立一個模塊(module)和一個視圖(view)。

rainier.js 
define(function (require) { 
  var http = require('plugins/http'), 
      ko = require('knockout'); 
  var url = 'http://api.flickr.com/services/feeds/photos_public.gne'; 
  var qs = {  
    tags: 'mount ranier',  
    tagmode: 'any',  
    format: 'json'  
  }; 
  return { 
     images: ko.observableArray([]), 
     activate: function () { 
       var that = this; 
       if (this.images().length > 0) { 
           return; 
       } 
      
       return http.jsonp(url, qs, 'jsoncallback').then(function(response) { 
          that.images(response.items); 
       }); 
     } 
   }; 
}); 
rainier.html 
<section> 
  <h2>Mount Rainier</h2> 
  <div class="row-fluid"> 
    <ul class="thumbnails" data-bind="foreach: images"> 
      <li> 
         <img style="width: 260px; height: 180px;" data-bind="attr:
 { src: media.m }"/> 
      </li> 
    </ul> 
  </div> 
</section>

我想你已經可以看出來它是怎麼工做的了。新模塊在activate回調方法中使用http插件調用Flickr的api去獲取圖片。而後將數據保存到images屬性中。Images是一個可被觀察的(observable)數組,頁面綁定這個數組並展現圖片。

將應用運行起來,能夠看到在導航欄中出現了兩項,你能在二者間進行前進和後退操做。你也可使用瀏覽器的返回按鈕。Durandal能作的事情遠不止這些。也許你該下載Starter Kit並仔細研究,就會發現一些更有趣的東西。又或者你應該將官方的示例程序下載下來,看看各類功能是如何工做的,例如發佈/訂閱消息、自定義模態對話框、組件、高級的視圖組合等等。若是你想看一些更酷的東西,能夠看看Kickstarter資助的系列培訓中咱們將構建的應用。

Durandal經過模塊化的方法,使得構建富客戶端,動態的JavaScript應用更加簡單。所以理所固然地,咱們的社區發展得很是快。咱們的計劃纔剛剛開始,但願你也能加入咱們的奇妙旅程。請瀏覽一下咱們的Kickstarter。2014年咱們已經有了一些很酷的目標,同時,也有一些很是棒的獎勵給你。Web正在發生改變,光明的將來指日可待,但願咱們在那裏相逢。

相關文章
相關標籤/搜索