今天我們來818《angularjs in action》的第三章controller和view。
1.Big Picture概覽圖
- View是angularjs編譯html后呈現出來的,需要編譯的是controller中的定義的屬性和方法以及directive中定義的指令。
- View和controller是獨立開來的,他們之間的紐帶就是圖中間的膠水——scope。Controller負責向scope中提供屬性和方法,便於和view層面的html進行交互。
- 方便起見,我們通常將controller和scope統一視為ViewModel。這樣就引出了我們見到的一個概念MVVM框架(Model-View-ViewModel),這也是angularjs遵循的框架理念。具體見下圖
仔細看看圖,再想想還有一個眾所周知的概念——MVC,對比下來,你是否體會到了什么?
2.What Is An Angularjs View
- 如果你打開angularjs的官網,你將會看到這樣一句話“HTML enchanced for web apps”。這在一定程度上肯定了angularjs也揭露了angularjs一個重要的特性,傳統html標簽以外的指令。
- 在scope中存入一個變量值$scope.name,便可以在html中通過<p>{{name}}</p>的方式展示出來。如果你想將一個數組放入scope中$scope.values=[1,2,3,4],那也沒問題,只需要在html中寫上<p ng-repeat=”value in values”>{{value}}</p>,就可以遍歷並展示整個數組。
- Angularjs提供了很多內置的指令,但是面對錯綜復雜的真實世界,angularjs顯得有些力不從心。所以angularjs團隊提供用戶可以編寫自定義的指令。(這是個long story,這里先不說,讓我們繼續controller和view之間的那些事兒~~~)
- 言歸正傳,View到底是什么?簡而言之,就是經過angularjs編譯DOM得到的頁面呈現。那我們就好好理解下“編譯”二字的具體含義。
- 編譯分為兩部分:compilation階段和linking階段。
- 當html加載完成后,angularjs就開始解析DOM節后並編譯其中包含的directives,這就是compilation階段的工作;
- 一旦html中的所有元素都編譯完了,angularjs就開始進入linking階段,負責鏈接到每個angularjs編譯條目對應的scope實例。
- 當angularjs的template被鏈接到相應的controller之后,就通過scope完成了view和controller之間的聯系,就猶如上圖中的膠水一般。具體可以參見圖
3.What Is An Angularjs Controller
我們說通過膠水scope建立起view和controller之間的聯系和交互。那么scope到底是什么,它又是如何實現view和controller之間相互通信的?深究后發現,scope就是一個帶有事件機制的POJO(Plain Old Javascript Object)。這些事件促成了angularjs中的digest cycle,從而同步view端和controller端,具體如下圖:
Angularjs有着一套自己的事件機制,添加事件,然后在應用的任何地方響應。發射事件的方式有兩種:$broadcast和$emit,他們除了發射事件的方向不一樣意外,別無二致。負責監聽和響應使用的是$on。
要使用事件機制就要有scope對象,比如你要在一個service中broadcast一個事件,就需要注入$rootScope。當然了,一般來說我們不直接注入$rootScope,而是將$rootScope注入放在一個高level的地方。$broadcast是向下發送事件,所以需要確保所有的scope對象都能夠響應事件,因為所有的scope對象都在$rootScope對象下面。一般來說,開發者都使用promises來處理services中的異步事件。
4.Properites and Expressions
接下來我們要搞懂兩個問題:綁定屬性和執行表達式。
4.1 ngRepeat
你如何展示一個對象數組,而且實現並沒有定義他們的布局等等,如果有個東西能夠定義一個template然后只要repeat每個對象就可以展示是不是炫爆了,沒錯,angularjs中的ngRepeat為您帶來了福音。
我們定義一個對象數組,其中有各個不同的status,通過ngRepeat來遍歷每個status然后顯示到頁面上。
這里的status in storyboard.statuses就是遍歷出controller中的statues數組,然后通過{{status.name}}實現雙向綁定,取到controller中各個status對應的name(To Do, In Progress, Code Review, QA Review, Verified)
4.2 Filters
過濾器可以過濾出你想要的數據格式和內容。比如在上例中可以使用|filter:{status:status.name},,這個表達式意思是說只返回那些匹配status.name的stories。
最終得到如下結果:
4.3 Expression
到目前為止,已經知道如何通過template和ngRepeat來展示stories集合了,那么如何展示、更新和刪除單個story detail頁面呢?
- display a story
這里做了一些准備工作,一個currentStory和editStory。(這里可以通過http://www.tuicool.com/articles/En6Jve了解下copy和extend的區別,深拷貝和淺拷貝)
頁面中定義如下:
注意:通過這個例子,可以看出angularjs是如何傳值,明白了angularjs這種里面的函數的參數的值從何而來。從本例來看,在頁面中通過ng-repeat得到當前current的這個story,並在ng-click事件中添加storyboard.setCurrentStory(story)函數,而且將story作為參數傳入,並在StoryboardController.js的setCurrentStory有其具體實現
- Update a story
更新story就是更新storyboard.detailForm中的元素,並將更新的只直接reflected到storyboard.editedStory中去(如果覺得有點迷糊,記得結合項目源碼看)。這里主要有storyboard.updateCancel(取消更新)和storyboard.updateSotry(確認更新)。
其中storyboard.updateCancel通過調用resetForm是的form恢復初始狀態,updateStory通過遍歷每個屬性並寫入到storyboard.currentStory對象中,一旦這個操作完成,還需要執行resetForm使得表格恢復初始狀態。
- Create a story
創建一個story和update的過程很像,只是我們不需要再選擇current story這個步驟了,直接創建后push保存就ok了。當storyboard.currentStory為null時,我們就隱藏update按鈕同時顯示create的按鈕。
- Delete a story
刪除一個story只需要得到從前台頁面通過ng-click傳過來的id就可以實現刪除了
至此,我們啃完了第三章,大概內容有:
- 了解angularjs中的view層;
- 了解angularjs中的controller用於定義屬性和方法存放在scope上,並且可以和view交互;
- 了解scope是一個POJO,是view和controller之間的膠水;
- 當屬性在scope中聲明,意味着可以直接綁定到view上;
- ngRepeat的介紹和使用;
- filter的介紹和使用;
- display、update、create、delete a story.
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。
友情贊助
如果你覺得博主的文章對你那么一點小幫助,恰巧你又有想打賞博主的小沖動,那么事不宜遲,趕緊掃一掃,小額地贊助下,攢個奶粉錢,也是讓博主有動力繼續努力,寫出更好的文章^^。
1. 支付寶 2. 微信