首頁  >  文章  >  web前端  >  關於Angularjs中的$apply及最佳化使用

關於Angularjs中的$apply及最佳化使用

不言
不言原創
2018-07-02 13:59:101585瀏覽

這篇文章主要為大家介紹了關於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>

##js:

$scope.name="张三";
setTimeout(function(){
$scope.name = &#39;李四&#39;;
//$scope.$apply()
},500)

首先,name等於張三,500ms後,我把他賦值為李四,但是,頁面上並沒有改變,依然是張三。


而,我們把

$scope.$apply()放開,就正常了,張三成功變成李四。

2.第三方外掛程式

html:

#

<p>Date: <input type="text" id="datepicker"></p>
<p>
<header>所选日期</header>
{{selectedDate}}
</p>

js:

$scope.selectedDate = &#39;&#39;;
$( function() {
 $( "#datepicker" ).datepicker({
 onClose: function( selectedDate ) {
 $scope.selectedDate = selectedDate;
 // $scope.$apply();
 }
 });
} );

這是jquery的datepicker插件,當我們選定日期後,下面的日期應該隨之顯現,而現在卻沒有。這種情況就必須依賴$apply(),才能更新視圖。

以上兩種情況,都因為不處於Angularjs上下文中,導致監聽不到資料的變化。而$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

我們把setTime的程式碼放到$timeout中

$timeout(function(){
$scope.name = &#39;李四&#39;;
},500)

這就能正常運作了,看,沒有討厭的apply了!

3.$evalAsync

最推薦的應該時這個方法了。如果目前剛好有一個digest循環在執行,那麼它就會把導致digest循環的操作,放到當前digest循環中去執行。而$timeout是要等到目前digest循環執行完,再執行一次digest循環才可以。所以evalAsync執行更快,效能更好。我們可以像$timeout那樣去呼叫它,也就是

$scope.$evalAsync(
   function( $scope ) {
   console.log( "$evalAsync" );
   }
  );

以上,就是今天要說的全部。 Angularjs中還藏著許多奧秘,和更好的使用方法,希望大家可以深入研究,分享出更好的文章。


以下是可執行的程式碼,大家可以探究探究:https://codepen.io/hanwolfxue/pen/yEZbYQ

以上就是本文的全部內容,希望對大家的學習有幫助,更多相關內容請關注PHP中文網!

相關推薦:

關於Angular4 內建指令的基本用法

#在angularJs中如何實作清除瀏覽器快取

#

以上是關於Angularjs中的$apply及最佳化使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn