作爲摘要循環,如果有100個作用域變量,並且如果我更改了一個變量,那麼它將運行所有變量的監視,對變量進行髒檢查。如何在angularjs中手動停止摘要循環
假設我有100個相互獨立的範圍模型變量。如果我在一個變量中進行更改,那麼我不想檢查所有其他99個變量。有沒有辦法做到這一點?如果是,如何?
作爲摘要循環,如果有100個作用域變量,並且如果我更改了一個變量,那麼它將運行所有變量的監視,對變量進行髒檢查。如何在angularjs中手動停止摘要循環
假設我有100個相互獨立的範圍模型變量。如果我在一個變量中進行更改,那麼我不想檢查所有其他99個變量。有沒有辦法做到這一點?如果是,如何?
令人驚訝的是,這通常不是問題,即使有成千上萬的綁定,瀏覽器也沒有問題,除非表達式很複雜。 how many watchers are ok to have
的共同答案是2000
。
解決方案:
這是相當距離AngularJS 1.3
開始容易,因爲one-time
綁定核心了。
我們可以使用一次綁定(::)
指令來阻止觀察者觀察不需要的變量。這裏,變量只會在&之後纔會被觀察一次,之後它不會更新該變量。
HTML:
<ul ng-controller="myCtrl">
<li ng-repeat="item in Lists">{{lots of bindings}}</li>
</ul>
控制器代碼:
app.controller('myCtrl', function ($scope, $element) {
$element.on('scroll', function() {
$scope.Lists = getVisibleElements();
$scope.$digest();
});
});
在$digest
,你只改變Lists
對象感興趣,不改變個人項目。然而,Angular仍會詢問每個觀察者的變化。
指令爲stop
和pause
摘要:
app.directive('stopDigest', function() {
return {
link: function (scope) {
var watchers;
scope.$on('stop', function() {
watchers = scope.$$watchers;
scope.$$watchers = [];
});
scope.$on('resume', function() {
if (watchers)
scope.$$watchers = watchers;
});
}
};
});
現在,控制器代碼應改爲:
<ul ng-controller="listCtrl">
<li stop-digest ng-repeat="item in visibleList">{{lots of bindings}}</li>
</ul>
app.controller('myCtrl', function ($scope, $element) {
$element.on('scroll', function() {
$scope.visibleList = getVisibleElements();
$scope.$broadcast('stop');
$scope.$digest();
$scope.$broadcast('resume');
});
});
參考文檔:https://coderwall.com/p/d_aisq/speeding-up-angularjs-s-digest-loop
謝謝。
這是一個非常特殊的用例,在摘要循環中進行獨佔/條件檢查,並且我認爲沒有分叉/篡改有角的核心是不可能的。
我會考慮重構你/ $watching
。也許使用ngModelController
的$viewChangeListeners
比$watch
更合適?
這是一個很好的問題,並強調了Angular 1.x中最大的缺陷之一。幾乎無法控制摘要循環的管理方式。它意味着是一個黑盒子,對於更大的應用程序,這可能會導致嚴重的性能問題。沒有角度的方式做你的建議,但有一些東西可以幫助你實現相同的目標(即 - 只有一件事情發生變化時更好的摘要循環表現)。我想推薦使用bind-notifier plugin。我與這個項目沒有任何關係,但是我將它用於我自己的項目,並取得了巨大的成功。
背後的想法是,你可以指定某些綁定只在特定事件發生時被$消化。
有使用插件的多種方法,但這裏是我發現必須有效的一個:
在模板文件,指定使用綁定的特殊綁定-通知語法:
<div>{{:user-data-change:user.name}}</div>
<div>{{:job-data-change:job.name}}</div>
除非通知他們,否則這兩個綁定在大多數摘要循環中不會被骯髒檢查。
在您的控制器,當用戶數據的變化,通知是這樣的綁定:
this.refreshUserData().then(() => {
$scope.$broadcast('$$rebind::user-data-change');
});
(以及類似的job-data-changed
)
有了這一點,user.name
綁定將只在廣播檢查。
有幾件事情要記住:
$emit
和$broadcast
本身可能會影響性能,因此請嘗試僅在$scope
樹的少部分(scope
s,幾乎沒有子女)調用它們。
因此,沒有這種方式,但明顯地,你可以使用bindonce指令來減少像{{:myVar}}這樣的頁面的監視器,它只會在它不會更新值爲 –
我不能使用一次性綁定。這將從變量中刪除手錶,我需要兩種方式綁定,因爲我正在使用ng-model變量作爲輸入框 –
也許嘗試使用'$ watchCollection' – malix