AngularJS學習心得--Module方法詳解
AngularJS是什麼?
AngularJs(後面就簡稱ng了)是一個用於設計動態web應用的結構框架。首先,它是一個框架,不是類庫,是像EXT一樣提供一整套方案用於設計web應用。它不僅僅是一個javascript框架,因為它的核心其實是對HTML標籤的增強。
何為HTML標籤增強?其實就是使你能夠用標籤完成一部分頁面邏輯,具體方式就是通過自定義標籤、自定義屬性等,這些HTML原生沒有的標籤/屬性在ng中有一個名字:指令(directive)。後面會詳細介紹。那麼,什麼又是動態web應用呢?與傳統web系統相區別,web應用能為使用者提供豐富的操作,能夠隨使用者操作不斷更新檢視而不進行url跳轉。ng官方也宣告它更適用於開發CRUD應用,即資料操作比較多的應用,而非是遊戲或影象處理類應用。
為了實現這些,ng引入了一些非常棒的特性,包括模板機制、資料繫結、模組、指令、依賴注入、路由。通過資料與模板的繫結,能夠讓我們擺脫繁瑣的DOM操作,而將注意力集中在業務邏輯上。
另外一個疑問,ng是MVC框架嗎?還是MVVM框架?官網有提到ng的設計採用了MVC的基本思想,而又不完全是MVC,因為在書寫程式碼時我們確實是在用ng-controller這個指令(起碼從名字上看,是MVC吧),但這個controller處理的業務基本上都是與view進行互動,這麼看來又很接近MVVM。讓我們把目光移到官網那個非醒目的title上:“AngularJS — Superheroic JavaScript MVW Framework”。
AngularJS中的Module類負責定義應用如何啟動,它還可以通過宣告的方式定義應用中的各個片段。我們來看看它是如何實現這些功能的。
一、Main方法在哪裡
如果你是從Java或者Python程式語言轉過來的,那麼你可能很想知道AngularJS裡面的main方法在哪裡?這個把所有東西啟動起來,並且第一個被執行的方法在哪裡?JavaScript程式碼裡面負責例項化並且把所有東西組合到一起,然後命令應用開始執行的那個方法在哪裡?
事實上,AngularJS並沒有main方法,AngularJS使用模組的概念來代替main方法。模組允許我們通過宣告的方式來描述應用中的依賴關係,以及如何進行組裝和啟動。使用這種方式的原因如下:
1.模組是宣告式的。這就意味著它編寫起來更加容易,同時理解起來也很容易,閱讀它就像讀普通的英文一樣!
2.它是模組化的。這就迫使你去思考如何定義你的元件和依賴關係,讓它們變得更加清晰。
3.它讓測試更加容易。在單元測試呂,你可以有選擇地加入模組,並且可以避免程式碼中存在無法進行單元測試的內容。同時,在場景測試中,你可以載入其他額外的模組,這樣就可以更好地和其他元件配合使用。
例如,在我們的應用中有一個叫做"MyAwesomeApp"的模組。在HTML裡面,只要把以下內容新增到<html>標籤中(或者從技術上說,可以新增到任何標籤中):
<html ng-app="MyAwesomeApp">
ng-app指令就會告訴AngularJS使用MyAwesomeApp模組來啟動你的應用。那麼,應該如何定義模組呢?舉例來說,我們建議你為服務、指令和過濾器分別定義不同的模組。然後你的主模組可以宣告依賴這些模組。
這樣可以使得模組管理更加容易,因為它們都是良好的、完備的程式碼塊,每個模組有且只有一種職能。同時,單元測試可以只加載它們所關注的模組,這樣就可以減少初始化的次數,單元測試也會變得更精緻、更專注。
二、載入和依賴
模組載入動作發生在兩個不同的階段,這一點從函式名上面就可以反映出來,它們分別是Config程式碼塊和Run程式碼塊(或者叫做階段)。
1、Config程式碼塊
在這一階段裡面,AngularJS會連線並註冊好所有資料來源。因此,只有資料來源和常量可以注入到Config程式碼塊中。那些不確定是否已經初始化好的服務不能注入進來。
2、Run程式碼塊
Run程式碼塊用來啟動你的應用,並且在注射器建立完成之後開始執行。為了避免在這一點開始之後再對系統進行配置操作,只有例項和常量可以被注入到Run程式碼塊中。你會發現,在AngularJS中,Run程式碼塊是與main方法最類似的東西。
三、 快捷方法
利用模組可以做什麼呢?我們可以用它來例項化控制器、指令、過濾器以及服務,但是利用模組類還可以做更多事情。如下模組配置的API方法:
1、config(configFn)
利用此方法可以做一些註冊工作,這些工作需要在模組載入時完成。
2、constant(name, object)
此方法會首先執行,所以你可以用它來宣告整個應用範圍內的常量,並且讓它們在所有配置(config方法)和例項(後面的所有方法,例如controller、service等)方法中可用。
3、controller(name,constructor)
它的基本作用是配置好控制器方便後面使用。
4、directive(name,directiveFactory)
可以使用此方法在應用中建立指令。
5、filter(name,filterFactory)
允許你建立命名的AngularJS過濾器,就像前面章節所討論的那樣。
6、run(initializationFn)
如果你想要在注射器啟動之後執行某些操作,而這些操作需要在頁面對使用者可用之前執行,就可以使用此方法。
7、value(name,object)
允許在整個應用中注射值。
8、factory(name,factoryFn)
如果你有一個類或者物件,需要首先為它提供一些邏輯或者引數,然後才能對它初始化,那麼你就可以使用這裡的factory介面。factory是一個函式,它負責建立一些特定的值(或者物件)。我們來看一個greeter(打招呼)函式的例項,這個函式需要一條問候語來初始化:
function Greeter(salutation) {
this.greet = function(name) {
return salutation + ' ' + name;
};
}
greeter函式示例如下:
myApp.factory('greeter', function(salut) {
return new Greeter(salut);
});
然後可以這樣來呼叫它:
var myGreeter = greeter('Halo');
9、service(name,object)
factory和service之間的不同點在於,factory會直接呼叫傳遞給它的函式,然後返回執行的結果;而service將會使用"new"關鍵字來呼叫傳遞給它的構造方法,然後再返回結果。所以,前面的greeter Factory可以替換成下面這個greeter Service:
myApp.service('greeter', Greeter);
每當我們需要一個greeter例項的時候,AngularJS就會呼叫新的Greeter()來返回一個例項。
10、provider(name,providerFn)
provider是這幾個方法中最複雜的部分(顯然,也是可配置性最好的部分)。provider中既綁定了factory也綁定了service,並且在注入系統準備完畢之前,還可以享受到配置provider函式的好處(也就是config塊)。
我們來看看使用provider改造之後的greeter Service是什麼樣子:
myApp.provider('greeter', function() {
var salutation = 'Hello';
this.setSalutation = function(s) {
salutation = s;
}
function Greeter(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}
this.$get = function(a) {
return new Greeter(a);
};
});
這樣我們就可以在執行時動態設定問候語了(例如,可以根據使用者使用的不同語言進行設定)。
var myApp = angular.module(myApp, []).config(function(greeterProvider) {
greeterProvider.setSalutation('Namaste');
});