雙向綁定是Angular的核心概念之一,它給我們帶來了思維方式的轉變:不再是DOM驅動,而是以Model為核心,在View中寫上聲明式標簽。然後,Angular就會在後臺默默的同步View的變化到Model,並將Model的變化更新到View。 雙向綁定帶來了很大的好處,但是它需要在後臺保持一隻“眼 ...
雙向綁定是Angular的核心概念之一,它給我們帶來了思維方式的轉變:不再是DOM驅動,而是以Model為核心,在View中寫上聲明式標簽。然後,Angular就會在後臺默默的同步View的變化到Model,並將Model的變化更新到View。
雙向綁定帶來了很大的好處,但是它需要在後臺保持一隻“眼睛”,隨時觀察所有綁定值的改變,這就是Angular 1.x中“性能殺手”的“臟檢查機制”($digest)。可以推論:如果有太多“眼睛”,就會產生性能問題。在討論優化Angular的性能之前,筆者希望先講解下Angular的雙向綁定和watchers函數。
雙向綁定和watchers函數
為了能夠實現雙向綁定,Angular使用了$watch API來監控$scope上的Model的改變。Angular應用在編譯模板的時候,會收集模板上的聲明式標簽 —— 指令或綁定表達式,並鏈接(link)它們。這個過程中,指令或綁定表達式會註冊自己的監控函數,這就是我們所說的watchers函數。
下麵以我們常見的Angular表達式({{}}
)為例。
HTML:
1
2
3
4
|
|
JavaScript:
1
2
3
4
5
6
7
8
9
|
|
這是一個自增長計數器的例子,在上面的代碼我們用了Angular表達式({{}}
)。表達式為了能在Model的值改變的時候你能及時更新View,它會在其所在的$scope(本例中為DemoController)中註冊上面提到的watchers函數,監控count屬性的變化,以便及時更新View。
上例中在每次點擊button的時候,count計數器將會加1,然後count的變化會通過Angular的$digest過程同步到View之上。在這裡它是一個單向的更新,從Model到View的更新。如果處理一個帶有ngModel指令的input交互控制項,則在View上的每次輸入都會被及時更新到Model之上,這裡則是反向的更新,從View到Model的更新。
Model數據能被更新到View是因為在背後默默工作的$digest迴圈(“臟檢查機制”)被觸發了。它會執行當前scope以及其所有子scope上註冊的watchers函數,檢測是否發生變化,如果變了就執行相應的處理函數,直到Model穩定了。如果這個過程中發生過變化,瀏覽器就會重新渲染受到影響的DOM來體現Model的變化。
在Angular表達式({{}}
)背後的源碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
|