[英]Conserving watchers in angular ? (ng-repeat POV)
我已經知道如何處理ng-repeat性能問題的常見模式(與觀察者一起),如: one-time-bind
, infinite scroll
etc
。
但我看到一個人的答案建議轉向指令。
好的,我開始采用簡單的舊方法
這個html有100個項目:
<div ng-repeat="e in ct.arr">
<div class='s'>
<span >name:{{e.name}} , age:{{e.age}} , height:{{e.height}}</span>
<hr>
</div>
這將產生301
觀察者,當我點擊一個按鈕時我可以更改第5'th
項目:
那么我想把它移到指令(就像建議的那樣):
現在HTML是:
<div ng-repeat="e in ct.arr">
<div class='s'>
<span my-event="e" ></span>
<hr>
</div>
</div>
指令:
.directive('myEvent', function() {
return {
scope: {
event: "=myEvent"
},
link: link,
}
function link(scope, element, attrs) {
var ev = scope.event;
element.text('name:'+ev.name +', age:'+ev.age+' , height:'+ev.height)
}
});
現在我只有101
觀察者,但現在按鈕沒有影響:
問題:
如果我是對的,100名觀察者是因為孤立范圍的直接別名是'='
。 但如果它是該項目的直接別名,為什么我沒有看到按鈕點擊后的修改?
如果我想看到修改,我是否會遇到301
觀察者? 還有什么我沒有想到的 - 可以做到嗎?
像Alainlb寫的那樣,你只是在創建時計算內容一次。 當然就像你在評論中寫一樣,使用template :'<span>name:{{event.name}} ,age:{{event.age}} , height:{{event.height}} </span>'
添加手表(每個{{ ... }}
是幕后的手表)。
想到的第一個解決方案是使用監視指令的項目。 深度監視具體,以便它可以檢測對象屬性的更改,而不僅僅是對實際對象引用的更改:
function link(scope, element, attrs) {
scope.$watch('event', function(ev) {
element.text('name:' + ev.name + ', age:' + ev.age + ' , height:' + ev.height);
}, true);
}
http://plnkr.co/edit/marpxMx5qin7mOlFwp3X?p=preview
分數:201手表
但我們可以做得更好; 因為我們正在手動觀察,所以=
scope綁定現在是多余的。 哦,然后scope: {}
配置為空; 我們甚至可以沒有范圍,既不是孤立的,也不是新的原型繼承的。 讓我們使用scope: false
(每次迭代可以節省1個范圍對象,對於許多迭代來說都是很好的增益)。
我們現在直接觀察my-event
屬性中給出的表達式:
.directive('myEvent', function() {
return {
scope: false,
link: link,
};
function link(scope, element, attrs) {
scope.$watch(
attrs.myEvent,
function(ev) {
element.text('name:' + ev.name + ', age:' + ev.age + ' , height:' + ev.height);
},
true
);
}
});
http://plnkr.co/edit/lvnIQCJMnniFlOeRseaZ?p=preview
分數:101手表
有一個問題:深度觀察產生較少的手表,但它們更昂貴,因為它們迭代觀察對象的每個屬性。 因此,真正的性能提升可能會低於它看起來的效果 - 101手表對301手表。 我們可以做得更好嗎?
在嘗試之前,我首先要測量101深表和301表之間的真正性能差異。 如果可以忽略不計,我們沒關系。 否則,我們可能會使用Javascript屬性getter和setter在我們的更新中變得“更聰明”,並且可能在對象上手動設置臟標志。 這將很復雜。
更好的方法是永遠不要改變對象的內部屬性(將其視為不可變 - 一般來說是一個好主意)並更改引用本身。 即:
vm.c10 = function (){
this.arr[4] = {
name: "aaaa",
age: "aaaa",
height: "aaaa"
};
};
然后你不再需要深入觀察(從scope.$watch
的參數中刪除, true
scope.$watch
)。 如果你可以強制執行對象是不可變的約定( Immutable.js anybody?),你是獨自工作,或者團隊(現在和將來)對這個約定有良好的溝通和理解,那么這種方法效果最好。 否則就會出現邪惡的錯誤。
這是因為你使用鏈接,編譯指令的html一次並顯示它
試試這個http://plnkr.co/edit/spYF935i5TIX9HApVTF4?p=preview
.directive('myEvent', function() {
return {
scope: {
event: "=myEvent"
}
, template :'<span>name:{{event.name}} ,age:{{event.age}} , height:{{event.height}} </span>'
}
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.