【譯】《精通使用AngularJS開發Web App》(四)--- 深刻視圖,模板系統,模塊和依賴注入

上一篇:【譯】《精通使用AngularJS開發Web App》(三)
下一篇:javascript

書名:Mastering Web Application Development with AngularJShtml

Chapter 1java

視圖

咱們已經見了這許多AngularJS模版的例子,應該認識到他並非「又出現一個模板語言」,但確實仍是有許多的不一樣(跟其餘模板語言相比)。不只是說框架的模板語法依賴於HTML,還容許咱們來擴展HTML的詞彙,並且還有能夠在沒有任何人工干預的狀況下刷新局部視圖這種的獨一無二的能力!數據庫

事實上,AngularJS 與 HTML 和 DOM 的聯繫更爲密切,由於它就是依賴瀏覽器來解析模版內容的(就跟瀏覽器會對任何其餘的HTML文檔所作的那樣)。在瀏覽器把標記文本轉化爲 DOM 樹以後,AngularJS就會進入這個解析好的DOM結構。而後,每當遇到一個指令,AngularJS就會執行它的邏輯,並將指令變爲動態的內容。編程

既然AngularJS 依賴於瀏覽器來解析模板,咱們就須要確保提供的模板是合格的HTML內容。要特別注意HTML標籤的正確閉合(不然的話,不會輸出錯誤信息,但視圖卻不會被正確的渲染出來)。AngularJS 必須在正確的DOM樹上工做。segmentfault

AngularJS 使得豐富HTML的詞彙表成爲可能(咱們能夠添加新的屬性或HTML元素,並教會瀏覽器應該如何解析他們)。這就像在 HTML 基礎上建立一門特定領域語言(domain-specific language),並指導瀏覽器如何理解新的指令。你可能常常會聽到AngularJS「教了瀏覽器一些新的技巧」。瀏覽器

聲明式模板視圖 - 勢在必行的控制器邏輯

AngularJS自帶了不少方便的指令,咱們將會在後面的章節中涵蓋其中的大部分。最重要的事情,其實不是去了解單個指令的語法和功能,而是 AnulgarJS 構建 UI 的背後的哲學思想。app

AngularJS 推廣了一套聲明式的構建 UI 的方式。在實踐中這意味着,模板會把重心放在如何描述一個指望的效果,而不是如何具體實現它。聽起來可能有點困惑,那就看個例子吧。框架

讓咱們想象一下這種狀況,咱們須要建立一個form,用戶能夠輸入一些簡短的文字,而後能夠點擊按鈕發送表單。固然這還涉及到一些用戶體驗的事情,好比文字長度須要限制在100字之內,若是超出範圍就禁用 發送 按鈕。用戶須要在他們輸入的時候知道還剩多少個字。若是剩餘的字數小於10,那麼提示文字就要改變樣式爲警告的狀態。也須要可以清除已經存在的文字。完成後的form可能看起來以下圖:
示例表單
上面這個需求不是特別有挑戰性,也只是一個普通的文本表單,儘管如此,這裏仍是因爲多須要整合的UI元素,好比,要確保按鈕的 disabled 禁用狀態能夠正常工做,剩餘字數要用恰當的樣式來準確的顯示等等。首次嘗試的實現代碼以下:dom

<div class="container" ng-controller="TextAreaWithLimitCtrl">
           <div class="row">
               <textarea ng-model="message">{{message}}</textarea>
           </div>
           <div class="row">
             <button ng-click="send()">Send</button>
             <button ng-click="clear()">Clear</button>
           </div>
   </div>

咱們仍是使用前面的代碼做爲起點,在那個基礎上繼續。首先,咱們須要顯示剩餘字數,這個至關容易,以下所示:

<span>Remaining: {{remaining()}}</span>

remaining() 函數定義在 TextAreaWithLimitCtrl 控制器中的 $scope 上,以下:

$scope.remaining = function () {
    return MAX_LEN - $scope.message.length;
};

而後,咱們須要在文本不符合字數限制的時候禁用 Send 按鈕。這個能夠用 ng-disabled 指令很容易的實現,以下:

<button ng-disabled="!hasValidLength()"...>Send</button>

這裏使用了一個固定模式。要操做UI的話,只需接觸模板的一小部分,而後根據模型的狀態(這裏就是文本的長度)描述一個指望的輸出結果(顯示剩餘字數,禁用按鈕等)便可。最有意思的地方在於,咱們不需在 JavaScript 代碼中持有任何對DOM元素的引用,咱們也不須要準確的操控DOM元素。如今咱們只需關注模型的變化,讓 AngularJS 去作那些枯燥繁重的工做去吧。咱們所須要作的只是在這種形式的指令中提供一些建議。

繼續回到咱們的例子中來,咱們還要確保剩餘字數的提示要在只剩下不多字數的時候改變樣式。這是一個能夠可實戰中學習另外一個聲明式UI的例子的好機會。以下所示:

<span ng-class="{'text-warning' : shouldWarn()}"> 
Remaining: {{remaining()}}
</span>

shouldWarn() 方法的實現以下所示:

$scope.shouldWarn = function () {
    return $scope.remaining() < WARN_THRESHOLD; 
};

CSS class 的變化是根據模型的變化而來的,可是咱們並無在 JavaScript 中寫任何的操做 DOM 的代碼!UI 會基於以聲明的方式表達的「想要幹嗎」而重繪。咱們用 ng-class 指令所表達的意思是:「每次字數超出限制,都要經過把 text-warning 加到 <span> 元素的 class 上面 來給用戶一個警示」。這跟下面這種說法是至關不一樣的 「當輸入一個新的字符,而且字數超出了限制,就去找到 <span> 元素,而後改變這個元素的 CSS class text-warning」。(譯註:兩種不一樣的思路,前一種是描述你所但願的狀態,後一種是徹底的把你要實現這種結果的過程描述出來)。

咱們這裏說的好像只是有點微妙的不一樣,但其實,聲明式的和命令式的是兩種至關對立的實現方式。命令式的編程,重點在於描述每個單獨的過程,並將結果導向但願獲得的結果。聲明式的方式,重點在於但願獲得的結果。至於要達到這個結果的那些獨立的步驟是由支持這種方式的框架所關心的。這就像是在說「親愛的 AngularJS,這就是當模型到某個狀態以後,我所但願的UI可以展現的狀態,如今呢,就請開始想一想何時以及如何來重繪這些UI吧」。

聲明式的編程一般更富有表達力,由於把開發人員從很是細微的、底層的指令(編碼)中解放出來了。產出的代碼一般都很是的簡潔、易於閱讀。但若要在工做中使用聲明的方式,就必須有裝備工具可以正確的理解更高級的指令。咱們的程序開始依賴於這些機器的決定,而且咱們須要放棄一些底層的控制權。使用命令式的方式,咱們擁有徹底的控制權,也能很好的協調好每個單獨的操做。咱們獲得了更多的控制權,這種「負責任」的代價就是要寫很是多的底層的、重複的代碼。

熟悉 SQL 語言的讀者會以爲這些聽起來都很是的熟悉(SQL 是一個針對請求臨時(adhoc)數據的很是富有表達力的聲明式的語言)。咱們簡單的描述一下須要獲得的結果(去fetch的數據),以後的就是去讓(關係型)數據庫去想該怎麼去拿到特定的數據了。絕大多數狀況下,這個過程都能完美的工做,咱們也能很快速的拿到咱們所想獲得的。固然也有一些狀況須要給出更多的提示(索引(indexes),查詢計劃提示(query planner hints)等等),或者手動控制數據檢索過程,以便優化性能。

AngularJS模板中的指令聲明式的描述了所指望的結果,因此呢,咱們得以從一步步的給出若是改變DOM元素的各個屬性(基於 jQuery 的應用一般須要如此)中解脫出來。AngularJS 極力推廣在模板上使用聲明式的編程,而在javascript代碼中是用命令式的(控制器和業務邏輯)。使用 AngularJS的話,咱們不多會使用到低級的、命令式的指令來操做DOM(惟一的例外是在指令裏面中的代碼)。

就經驗而言,千萬不要在 AngularJS控制器中操做 DOM 元素。在控制器中獲取一個DOM的引用,並操做DOM的屬性,是在用命令式的方式控制UI -- 這是跟 AugularJS 構建 UI 的思想相悖的。

使用 AngularJS 指令寫出來的聲明式的 UI 模板能夠很迅速的描述出複雜的、交互的UI。AngularJS 會自主作出全部這些底層決定什麼時候以及如何操做DOM樹的部分。絕大多數時候 AngularJS 會作出「正確的事情」,並更新UI爲所預期的(也很是及時的)。不過,理解 AngularJS 的內部工做原理也很是的重要,這樣的話咱們就能夠在須要的時候給框架一些適當的提示。這裏的狀況跟 SQL 又很是的類似,大多數狀況下,咱們都不須要爲查詢計劃的工做狀況操心。但當咱們遇到性能問題的時候,瞭解查詢計劃是如何下決定的就很是有價值了,這樣一來咱們就能夠給它提供更多的意見。這一樣適用於 AngularJS 的UI 管理:咱們須要瞭解背後的機制,以便於更高效的使用模板和指令。

模塊和依賴注入

細心的讀者可能已經發現了,到目前爲止所用到的例子都是使用的全局的構造函數來定義控制器的。可是,全局的狀態是邪惡的,它危及了應用的結構,讓代碼更難以維護,測試,和閱讀。AngularJS 毫不會建議使用全局狀態的。相反,它提供了一整套的 API,能夠很方便的定義模塊,在這些模塊中註冊對象。

AngularJS中的模塊

我麼一塊兒來看看怎麼把一個醜陋的,全局定義的控制器轉換爲同等的模塊化的定義。以前的控制器是這麼聲明的:

var HelloCtrl = function ($scope) { 
    $scope.name = 'World';
}

模塊化以後是這樣的:

angular.module('hello', []) 
    .controller('HelloCtrl', function($scope){
        $scope.name = 'World';
    });

AngularJS 自身定義了一個全局的 angular 名字空間。這個名字空間提供了不少不一樣類型的工具和方便的方法,module 就是這些方法的其中一個。module 會扮演一個其餘的AngularJS須要管理的對象(控制器、服務等)的容器。正如咱們以後就會看到的,除了簡單的名稱空間和代碼組織以外,模塊還有很是多的東西須要學習。

要定義一個新的模塊,咱們須要給 module 方法的第一個參數提供模塊的名字。第二個參數指定所須要依賴的模塊(在以前的模塊中,咱們沒有依賴與任何其餘模塊)。

angular.module 方法的調用會返回一個新建立的模塊的實例。一旦咱們是用這個實例,就能夠開始定義新的控制器了。這很是的簡單,只需使用以下參數來調用 controller 便可:
- 控制器的名字(字符串類型)
- 控制器的構造函數

全局定義的控制器構造函數只適用於快速示例和原型開發。永遠不要在大型的、真實的應用中使用全局定義的控制器。

如今已經定義了一個模塊,但咱們還須要通知 AngularJS 它的存在。這是經過給 ng-app 屬性提供一個值來完成的,以下:

<body ng-app="hello">

一個常常犯的錯誤就是忘記了在 ng-app 屬性中指定模塊的名字,這也會形成一些常見的困惑。在 ng-app 屬性中省略模塊名稱會引發錯誤,說明有未定義的控制器。

轉載請註明來自[超2真人]
本文連接:http://www.peichao01.com/static_content/doc/html/Mastering_Web_Application_Development_with_AngularJS_4.html

相關文章
相關標籤/搜索