1. 程式人生 > >angularjs在程式碼中改變了 model 的值,view 卻沒有更新

angularjs在程式碼中改變了 model 的值,view 卻沒有更新

今天在完成專案任務時,遇到一個問題資料初始繫結時沒有問題,然後通過在百度地圖 API提供的函式中修改了 model(ng-model 繫結在輸入框上),在頁面中不能實時更新,但是點選其他的輸入框或者按鈕時,就可以更新,查看了很多資料後,發現了上面的那篇文章,太感謝作者了。

引用文章中的一段
什麼時候需要人為的呼叫$apply()呢
如果AngularJS總是將我們的程式碼放在$apply()中並且執行$digest迴圈,那麼,什麼時候需要我們人為的呼叫$apply呢?事實上,AngularJS已經很明確的告訴我們了。AngularJS只會關心在AngularJS的執行上下文中的發生的資料模型(model)的變化(比如,改變資料的程式碼在$apply
()裡面)。AngularJS內建的指令也會自動觸發$digest迴圈所以任何資料模型(model)的改變都會反映到檢視中。但是,如果我們更改一個不在AngularJS執行上下文中的資料模型(model),就需要人為的呼叫$apply()來提醒AngularJS資料發生變化了。就像是要告訴AngularJS,我們改變了一些資料,他應該啟用監聽器以便於讓我們所做的改變能夠反映出來。 例如,當使用Javascript的setTimeout()函式來更新一個數據模型的時候,AngularJS就沒辦法知道你改變了資料模型。這種情況下,呼叫$apply()來觸發$digest迴圈就是你的責任了。類似的,如果你寫了一個指令,這個指令是設定了一個DOM事件監聽器,更改資料模型的程式碼在事件處理函式裡,那麼,也需要呼叫$apply
()來保證更改能夠反映出來。

從上面這一段我知道了,我的資料模型變化不在 Angularjs 的執行上下文中,使用導致 angularjs 不知道資料傳送變化也就沒有做出反映,所以我手動人為的呼叫了$apply 解決了問題。

上文中的例子

讓我們來看個例子。假設有一個頁面,我們想在頁面載入完之後兩秒顯示一個資訊。我們可能這樣寫:

<body ng-app="myApp">
    <div ng-controller="MessageController">
        Delayed Message: {{message}}
    </div>  
</body>
/* 沒有$apply()會發生什麼 */
angular.module('myApp', []).controller('MessageController', function ( $scope ) { $scope.getMessage = function () { setTimeout(function () { $scope.message = 'Fetched after 3 seconds'; console.log('message:'+$scope.message); }, 2000); }; $scope.getMessage(); }); 通過執行這個例子,我們會發現,在兩秒之後,函式開始執行,並且更新資料模型。但是,檢視卻沒有更新。原因我們也應該猜到了,我們忘了呼叫$apply()。因此,我們需要像下面這樣來寫我們的getMessage()函式。 全選複製放進筆記/* 使用了$apply()會發生什麼 */ angular.module('myApp', []).controller('MessageController', function ( $scope ) { $scope.getMessage = function () { setTimeout(function () { $scope.$apply(function () { //wrapped this within $apply $scope.message = 'Fetched after 3 seconds'; console.log('message:' + $scope.message); }); }, 2000); }; $scope.getMessage(); }); 執行更新後的例子,兩秒之後,我們就能夠看到檢視更新了。我們所做的唯一的改變就是將程式碼放進了$scope.$apply()中。這樣,就能自動的去呼叫$rootScope.$digest(),然後,監聽器就會啟動,檢視就會更新了。 注意

再次感謝文章作者