angularJS——數據更新了但是view(視圖)層卻未更新問題及解決方法


搬運自:https://www.cnblogs.com/yky-iris/p/9251230.html?utm_source=debugrun&utm_medium=referral

 

視圖不更新問題及原因: 在原生js或者第三方框架下,修改model,是有可能不會觸發視圖更新的,比如setTimeout、jquery插件。因為他們脫離了Angularjs的上下文,Angularjs並不能監聽到數據的改變。

解決方法:利用$apply()手動更新視圖,如下。(注意這是最不推薦的解決方法)

html:

<p>{{name}}</p>

js:

$scope.name="張三";
setTimeout(function(){
    $scope.name = '李四';
    //$scope.$apply()
},500)

 

  一. $apply(),digest概念  

 

  $apply()函數的作用: 可以從Angular框架的外部讓表達式在Angular上下文內部執行。

  $apply()函數工作原理:相當於一個觸發器,它的作用就是觸發digest循環,從而更新視圖。

  digest是什么?:digest是Angularjs的核心,是它實現了神奇的數據綁定。凡是觸發事件,必會觸發digest循環,比如ng事件,click,change,實際上都是觸發了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中,注意:需要在相應的factory或者service中引入——mianApp.controller('listController', function($scope,$http,$timeout) {···})

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

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

(3). $evalAsync

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

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

 

附:當http請求為異步時,數據可能無法獲取,視圖也就無法更新。此時將請求改為同步,或用以上更新數據的四種方法也可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM