在開始介紹angular原理以前,咱們有必要先了解下mvvm模式在angular中運用。雖然在angular社區一直將angular統稱爲前端MVC框架,同時angular團隊也稱它爲MVW(Whatever)框架,但angular框架總體上更接近MVVM模式。下面是Igor Minar發佈在Google+ https://plus.google.com/+IgorMinar/posts/DRUAkZmXjNV的文章內容:前端
MVC vs MVVM vs MVP. What a controversial topic that many developers can spend hours and hours debating and arguing about.angularjs
For several years +AngularJS was closer to MVC (or rather one of its client-side variants), but over time and thanks to many refactorings and api improvements, it’s now closer to MVVM – the $scope object could be considered the ViewModel that is being decorated by a function that we call a Controller.web
Being able to categorize a framework and put it into one of the MV* buckets has some advantages. It can help developers get more comfortable with its apis by making it easier to create a mental model that represents the application that is being built with the framework. It can also help to establish terminology that is used by developers.api
Having said, I’d rather see developers build kick-ass apps that are well-designed and follow separation of concerns, than see them waste time arguing about MV* nonsense. And for this reason, I hereby declare AngularJS to be MVW framework – Model-View-Whatever. Where Whatever stands for 「whatever works for you」.架構
Angular gives you a lot of flexibility to nicely separate presentation logic from business logic and presentation state. Please use it fuel your productivity and application maintainability rather than heated discussions about things that at the end of the day don’t matter that much.mvc
在文中特別指出angular在屢次的API重構和改善,它愈來愈接近於MVVM模式,$scope能夠被認爲是ViewModl,而Controller則是裝飾、加工處理這個ViewModel的JavaScript函數。做者更但願你們關注於實現一個成功的,具備好的設計以及遵循「分離關注點」原則的應用程序,而不是去爭論MV*,因此他將angular稱爲MVW框架,是什麼並不重要,只要適合你的應用就行。app
MVVM模式是Model-View-ViewMode(模型-視圖-視圖模型)模式的簡稱,其最先出如今微軟的WPF和Silverlight框架中。MVVM模式利用框架內置的雙向綁定技術對MVP(Model-View-Presenter)模式的變型,引入了專門的ViewModel(視圖模型)來實現View和Model的粘合,讓View和Model的進一步分離和解耦。MVVM模式的優點有以下四點:框架
- 低耦合:View能夠獨立於Model變化和修改,同一個ViewModel能夠被多個View複用;而且能夠作到View和Model的變化互不影響;
- 可重用性:能夠把一些視圖的邏輯放在ViewModel,讓多個View複用;
- 獨立開發:開發人員能夠專一與業務邏輯和數據的開發(ViewModel),界面設計人員能夠專一於UI(View)的設計;
- 可測試性:清晰的View分層,使得針對表現層業務邏輯的測試更容易,更簡單。
下面是angular中關於MVVM模式的運用:frontend
在angular中MVVM模式主要分爲四部分:mvvm
- View:它專一於界面的顯示和渲染,在angular中則是包含一堆聲明式Directive的視圖模板。
- ViewModel:它是View和Model的粘合體,負責View和Model的交互和協做,它負責給View提供顯示的數據,以及提供了View中Command事件操做Model的途徑;在angular中$scope對象充當了這個ViewModel的角色;
- Model:它是與應用程序的業務邏輯相關的數據的封裝載體,它是業務領域的對象,Model並不關心會被如何顯示或操做,因此模型也不會包含任何界面顯示相關的邏輯。在web頁面中,大部分Model都是來自Ajax的服務端返回數據或者是全局的配置對象;而angular中的service則是封裝和處理這些與Model相關的業務邏輯的場所,這類的業務服務是能夠被多個Controller或者其餘service複用的領域服務。
- Controller:這並非MVVM模式的核心元素,但它負責ViewModel對象的初始化,它將組合一個或者多個service來獲取業務領域Model放在ViewModel對象上,使得應用界面在啓動加載的時候達到一種可用的狀態。
View不能直接與Model交互,而是經過$scope這個ViewModel來實現與Model的交互。對於界面表單的交互,經過ngModel指令來實現View和ViewModel的同步。ngModelController包含$parsers和$formatters兩個轉換器管道,它們分別實現View表單輸入值到Model數據類型轉換和Model數據到View表單數據的格式化。對於用戶界面的交互Command事件(如ngClick、ngChange等)則會轉發到ViewModel對象上,經過ViewModel來實現對於Model的改變。然而對於Model的任何改變,也會反應在ViewModel之上,而且會經過$scope的「髒檢查機制」($digest)來更新到View。從而實現View和Model的分離,達到對前端邏輯MVVM的分層架構。
angular中MVVM模式的實現,以領域Model爲中心思惟,遵循「分離關注點」設計原則,這也是與jQuery以DOM驅動的思惟所不一樣之處。因此咱們在作angular開發的時候應該謹記下面幾點:
毫不要先設計你的頁面,而後用DOM操做去改變它
在以往的jQuery開發中,咱們會首先設計頁面DOM結構,而後在利用jQuery來改變DOM結構或者實現動態交互效果。由於jQuery是爲DOM驅動而設計的,對於擁有大量複雜的前端交互的項目,JavaScript的邏輯變得愈來愈臃腫,交互邏輯分散各處。
在MVVM模式下的angular開發中, 咱們首先須要在腦子裏掛着Model的弦。不能老想着「我有XXX這個DOM,我但願讓它作XXX這種動態效果」,咱們須要從要完成的目標開始思考咱們須要或擁有怎麼樣的Model數據,而後設計咱們的應用, 最後纔是設計視圖,並用$scope來粘合它們。
Directive不是封裝jQuery代碼的「天堂」
如上條所述,咱們不能一開始就去想如何利用DOM操做的方法去實現應用目標,而後「堂而皇之」的寫上一堆jQuery的代碼,並將其封裝到angular的directive中,最後不得不加上$scope.$apply()來通知angular你的ViewModel的改變,須要啓動「髒檢查機制」來更新你的改變到View。做者在多個客戶項目中看見這種將Directive做爲封裝jQuery代碼「天堂」的例子,其實對於這類問題,大部分狀況下,咱們均可以用不多了angular代碼將其重構爲真正的angular way。特別在ng社區常常看見在angular directive中利用jQuery的on方法綁定click、keydown、blur等事件的代碼,大部分狀況咱們都能以對應的ng事件(ngClick、ngChange、ngBlur)來重構它們。
對於這類問題,首先咱們應該儘可能嘗試複用angular的內置指令,以真正的angular way去思考咱們的問題,請慎重的引入jQuery的DOM方法和操做。
關於angular MVVM模式的資料,你還能夠參考視頻:https://frontendmasters.com/courses/angularjs-mvc-mvvm-mvwhatever/#v=ypur7bfbcq。