這篇文章主要為大家介紹了關於Angularjs中$apply及優化使用的相關資料,文中透過範例程式碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧
前言
對於一個在前端屬於純新手的我來說,Javascript都還是一知半解,要想直接上手angular JS,遇到的阻力還真是不少。不過我相信,只要下功夫,即使是反人類的設計也不是什麼大的問題。
今天,我們要聊得是Angularjs中的小明星$apply。當我們資料更新了,但是view層卻沒反應時,總是能聽到有人說,用apply吧,然後,懵懂無知的我們,在賦值程式碼後面加了$scope.$apply()
,然後就驚喜的發現。噢,真的更新了。
然而,有些時候,編譯器會無情的給你回傳
Error: $digest already in progress
那麼,導致這些現象的原因時又是什麼的呢? $apply究竟做了啥?聽我慢慢到來。
一.$apply的作用
#$apply()函數可以從Angular框架的外部讓表達式在Angular上下文內部執行。
上面是AngularJs權威教學中的一句話。什麼意思呢?
首先,你要清楚,在原生js或第三方框架下,修改model,是有可能不會觸發視圖更新的,例如setTimeout、jquery外掛。為什麼?因為他們脫離了Angularjs的上下文,Angularjs並不能監聽到資料的改變。看例子。
1.setTimeout
html:
#<p>{{name}}</p>
$scope.name="张三"; setTimeout(function(){ $scope.name = '李四'; //$scope.$apply() },500)
$scope.$apply()放開,就正常了,張三成功變成李四。
2.第三方外掛程式
html:#
<p>Date: <input type="text" id="datepicker"></p> <p> <header>所选日期</header> {{selectedDate}} </p>
$scope.selectedDate = ''; $( function() { $( "#datepicker" ).datepicker({ onClose: function( selectedDate ) { $scope.selectedDate = selectedDate; // $scope.$apply(); } }); } );
其實$apply相當於一個觸發器,它的作用就是觸發digest循環,從而更新視圖。
在digest是Angularjs的核心,是它實作了神奇的資料綁定。凡是觸發事件,必會觸發digest循環,比如,我們數值的ng事件,click啊,change,實際上都是觸發了digest循環。 所以,我們所做的事,其實就是手動觸發了digest循環。關於digest循環,屬於題外話,這裡不做太多介紹,想深入了解的同學,可以看看書籍,或百度。二.更好地運用digest循環
#在Angularjs中,除了$apply可以觸發digest循環外,還有其他的方法,也可以觸發此循環。而且$apply往往時最壞的選擇。下面推薦一些更好的選擇。1.$digest
$scope.$digest()的速度要比$apply快,因為它只更新當前作用域和子作用域的值,對於父作用域時不管的。而$apply還要評估父作用域,這就大大消耗了效能。
2.$timeout
用$timeout去取代你的setTimeout,$timeout作為Angularjs的自帶服務,當然時更契合Angularjs環境啦。它會隱性觸發digest循環,而且它會延遲執行,會在上一個digest循環完成後的下一刻,觸發digest循環,這樣就不會出現上文所說的$digest already in progress
$timeout(function(){ $scope.name = '李四'; },500)
3.$evalAsync
最推薦的應該時這個方法了。如果目前剛好有一個digest循環在執行,那麼它就會把導致digest循環的操作,放到當前digest循環中去執行。而$timeout是要等到目前digest循環執行完,再執行一次digest循環才可以。所以evalAsync執行更快,效能更好。我們可以像$timeout那樣去呼叫它,也就是$scope.$evalAsync( function( $scope ) { console.log( "$evalAsync" ); } );
#
以上是關於Angularjs中的$apply及最佳化使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!