javascript
AngularJS $watch 性能杀手
雙向綁定是AngularJS核心概念之一,它給我們帶來了思維的轉(zhuǎn)變,不再是以DOM為驅(qū)動,而是以Model為核心,View中寫上聲明式標(biāo)簽(指令或{{}}),AngularJS會在后臺默默同步View到Model,并將Model的變化更新到View。其雖然帶來了極大好處,但是需要有一種有性能隱患的“臟檢查機(jī)制”,隨時觀察所有綁定值的變化,如果這些需要觀察的值太多,就會產(chǎn)生性能問題。
一、watchers函數(shù)
AngularJS利用$watch API來監(jiān)控$scope上Model的變化,AngularJS應(yīng)用在編譯模版的時候,會收集模版上的聲明式標(biāo)簽-指令或表達(dá)式,并鏈接它們,這個過程指令或表達(dá)式會注冊自己的監(jiān)控函數(shù),即watchers函數(shù)。
有個AngularJS表達(dá)式{{}},其會在其所在的$scope中注冊watchers函數(shù)(watch是監(jiān)控mode變化,observe是監(jiān)控DOM中屬性變化),監(jiān)控Mode中的count屬性的變化,以便能更新到view。每次點擊Button時候,count計數(shù)器加1,觸發(fā)digest過程將變化同步到View上。這里是單向更新從Model更新到View上。如果界面上有個帶有ngModel指令的input控件,View上每次輸入都會被及時更新到Model上。
Model上的數(shù)據(jù)被更新到了View,背后是臟檢查機(jī)制被觸發(fā),它會執(zhí)行當(dāng)前$scope及其所有子$scope上注冊的watcher函數(shù),如果變化了就執(zhí)行相應(yīng)處理函數(shù),直到Model穩(wěn)定了,如果這個過程中Model發(fā)生了變化,瀏覽器會重新渲染DOM來反應(yīng)Model變化。
另外,AngularJS會在編譯階段手機(jī)所有指令,表達(dá)式{{}}會被解析成一種特殊的指令:addTextInterpolateDirective;在link階段,就會利用$watch的API來注冊watchers函數(shù),所以,表達(dá)式也會成為digest循環(huán)中watchers的一員。
不僅Angular表達(dá)式,其他的指令如ngShow、ngHide和ngBind,都會通過$watch API添加watchers函數(shù)。ngBind需要一個HTML節(jié)點,并以attribute屬性標(biāo)記的方式。
所以,如果有太多watchers函數(shù),那么在每次digest循環(huán)時候,肯定會慢下來,這是臟檢查機(jī)制的性能瓶頸,超過2000個watchers,就會感到明顯卡頓,所以,減少$watch,去掉不必要的$watch。在開發(fā)時候,盡量減少顯式使用$Scope.$watch,AngularJS很多內(nèi)置的指令已經(jīng)滿足大部分的業(yè)務(wù)需求,如ngChange,ngClick,不需要額外添加$watch。
二、one-time綁定
如果sessions有300個,那么這個循環(huán)會產(chǎn)生300*5+1(ngRepeat本身)個$watch,每次點擊likeSession時候,會檢查name,room等5個屬性是否會變化,而其實這5個屬性一旦綁定是不會變化的,沒必要watch,這個時候可以使用one-time綁定。
AngularJS的單次綁定在1.3版本引入,單次表達(dá)式在第一次digest后,將不再計算(檢測屬性變化),寫法是在表達(dá)式前邊加個“:”前綴,如下:
? ? ?
? ?三、滾屏加載
一種可行的性能解決方案,用于大量數(shù)據(jù)集顯示的時候,又不想分頁,所以一般放在頁面底部,當(dāng)滾動屏幕到達(dá)底部時候,就嘗試加載一個序列的數(shù)據(jù)集,追加到底部。可以用開源組件ngInfiniteScroll。
轉(zhuǎn)載于:https://www.cnblogs.com/shawnhu/p/8522072.html
總結(jié)
以上是生活随笔為你收集整理的AngularJS $watch 性能杀手的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Delphi编程修改ProgressBa
- 下一篇: Spring 环境与profile(一)