宋濤 王玉峰 呂思思
[摘要]AngularJs是新興的JavaScriptMVC框架,它為業界帶來了重大的變化,包括對模塊化(templating)的創新實現,以及數據的雙向綁定(two-way data binding),這些特性使得它強大而易用。大多數開發者認為,與其他框架相比,AngularJS明顯縮減了項目所需的代碼量。AngularJS是軟件中的杰作,它強調測試與代碼質量,在JavaScript生態圈內堪為表率,它的優質與創新,催生了周圍活躍的程序員社區,這反過來又讓AngularJS的人氣更加旺盛。下面我們來概述這項技術。
[關鍵詞]JavaScript MVC框架;數據的雙向綁定;單頁web應用
1邂逅AngularJS
AngularJS是采用JavaScript語言編寫的客戶端MVC框架,幫助開發者編寫現代化的單頁面(single-page)應用。它尤其適合編寫有大量CRUD(增刪改查)操作的,具有Ajax風格的富客戶端應用。
2熟悉框架
AngularJS是近年來不斷涌現的客戶端MVC框架中的新成員,它的出眾要歸功于創新的模板系統、友好的開發過程和可靠的工程實踐。下面先來看看模板系統的獨特之處。
1)使用HTML作為模板語言
2)無須對DOM進行顯式刷新,因為Angular.IS可以通過用戶動作、瀏覽器事件、模型變化來決定在何時刷新何類模板。
3)有趣的和可擴展的組件子系統能夠教會瀏覽器如何解釋自定義的HTML標簽及屬性。
AngularJS最顯而易見的部分,也許就是上述的模板系統,但是,AngularJS并不只是簡單地包裝一些與開發單頁面web應用相關的功能與服務。
實際上,AngularJS還隱藏著不少珠璣,如依賴注入及可測試性。通過依賴注入,可以用短小精煉且仔細測試過的服務來組建web應用。另外,AngularJS框架的設計和周邊的工作群,在開發應用的每個階段都鼓勵良好的測試實踐。
3AnguIarJS中的MVC模式
當前大部分web應用都基于知名的模型一視圖一控制器(MVC)模式的某形態。但是準確來說,MVC并不是編程模式,而是更高級的框架模式,因此相當抽象。更糟糕的是,當前有很多MVC模式的變種和派生,開發者們都在按照自己對MVC的理解在設計架構。這導致了同樣的名字(MVC)用于描述不同的架構和編碼方式。
3.1控制器
控制器的主要職責是初始化作用域實例。在實踐中,初始化邏輯又可以再分為:
1)提供模型的初始值。
2)增加UI相關的行為(函數)以擴展$scope對象。
控制器實際上就是JavaSeript函數,它們不需要擴展任何AngularJS特定的類,也不需要調用任何特定的AngularJS API,就可以正常工作。
3.2模型
AngularJS的模型實際上就是普通的JavaScript對象。與控制器類似,不需要特別的去擴展任何AngularJS的底層類,也不用去構造模型對象。
可以再模型層中使用任何當前存在的純JavaScript的類或對象。模型可擁有的屬性也不僅限于原始值,任何有效的JavaSeript對象或數都是可以的。只需要將模型簡單地指派給$scope,AngularJS就可確認它的存在。
3.3視圖
實際上,AngularJS與HTML和DOM有著更加緊密的聯系,因為AngularJS依靠瀏覽器去解析模板文本。瀏覽器將文本轉換成DOM樹之后,AngularJS參與進來,開始遍歷解析好的DOM結構。當遇到指令時。AngularJS就執行相關邏輯,將指令轉換成頁面的動態部分。
AngularJS擴展了HTML的詞匯庫,這類似于創造了一門基于HTML的領域特定語言。并指導瀏覽器如何理解它。因此,常聽到AngularJS“教瀏覽器新把戲”的說法。
4聲明式模板視圖——命令式控制器邏輯
AngularJS提供了很多便利的指令,然而,重要的不是這些指令的語法或功能,而是隱藏在表象之下的關于如何構建UI組件的AngularJS哲學。
AngularJS提倡聲明式UI結構。在實踐中,這意味著模板專注于描述所需要的效果,而非其實現。下面我們舉例來說明。
我們希望創建一個讓用戶可以輸入短消息的表單,然后點擊按鈕來發送它。這里有些特別的用戶體驗需求,短信息字數要限制在100字以內,一旦超出此限制,“Send”(發送)按鈕就要被禁用掉。當用戶輸入消息時,他應該知道還可以輸入多少字。一旦剩余字數小于10,就標示它的數字應該改變顯式樣式,以警告用戶。另外,它還應該可以清除用戶已經輸入的消息。
上面的需求是相當標準的文本表單,沒有多少挑戰性。盡管如此,也需要很多UI元素協同工作,例如,正確管理按鈕的disabled狀態,采用適當樣式顯示剩余可輸入的準確字數等。代碼如下:
我們用上面的代碼作為基礎。首先,要顯示剩余字數。代碼如下:
其次,在短消息超出字數限制時,禁用“Send”按鈕。這可以用ng-disabled指令搞定,代碼如下:
我們看到了重復出現的模式:僅需修改模板的很少一部分,就可以操縱UI,用模型狀態得出想要的結果。令人激動的是,不用在JavaScript代碼中保存任何對DOM元素的引用,也不用顯式地操縱DOM元素。我們只是專注于模型的變化,而讓AngularJS去做辛苦的工作。所有需要做的,只是以指令的形式去提供一些提示而已。
再回到上面的例子。下一步是,當可以輸入的文字數量已經不多時,改變剩余字數的顯式樣式。這里可以看到更多的命令式UI實例,代碼如下:
模型的改變驅動了CSS類的改變。而且,在代碼的任何地方都沒有顯式的DOM操作邏輯。uI基于聲明式的表達“愿望”,而重新繪制。Ng-class指令所表述的是這樣:“每次當用戶輸入快要超出字數限制的時候,應該看到警告,元素應該有text—warningCSS類。”這和另一種表述方式截然不同:“當輸入新的字符促使字符數量超出限制時,找到一個元素,并為此元素添加text-warning CSS類。”
以上兩個表述雖然聽起來差別不大,但是,實際上聲明式和命令式是針鋒相對的。命令式編程風格專注于描述通向理想結果的步驟,而聲明式編程風格專注于描述結果本身,步驟則主要由支持的框架來處理。這就好像說:“親愛的AngularJS,當模型在特定狀態時,我想要UI看起來是這樣。去吧,決定何時及怎樣重繪UI吧!”
通常來說,聲明式編程風格更具表現力,它讓開發者從嚴格的底層實現中解放出來,寫出簡潔易讀的代碼。但是,為了讓聲明式編程風格工作,需要能夠正確解釋高級命令的機制。一方面,程序要依賴這些機制,就要放棄某種程度的底層控制。另一方面,如果采用命令式編程風格,就可以控制一切調整每個細節。但是,“掌控一切”的代價,就是要編寫大量底層的、重復的代碼。
AngularJS的指令用聲明表達出了需要的效果,所以不用再去按部就班地修改DOM元素。AngularJS提倡在模板中使用聲明式編程風格,而在JavaScript代碼中使用命令式編程風格。有了AngularJS的支持,很少需要步驟詳細的底層DOM操縱(唯一的例外是實現指令的代碼)。
由AngularJS指令編寫的聲明式的uI模板,能夠快速地描述復雜的交互性UI。AngularJS會接管何時及如何操縱DOM樹的所有底層決定。大部分情況下,AngularJS做“正確的事”,并如期望的那樣,及時更新UI。但是,理解AngularJS的內部工作機制依然很重要,這樣可以在AngularJS需要時,為它提供適當的線索。可以運用SOL的比喻,大部分情況下我們不需要擔心查詢規劃器是如何做出決定的,以便于我們為它提供更多的線索。同樣的道理也適用于AngularJS所管理的UI:想要更有效地使用模板和指令,就要了解更多的內部機制。
[責任編輯:王偉平]