Skip to content

Commit f74d072

Browse files
committed
Reduce keySplices to minimum change set before notifying. Fixes #2261
1 parent 7497729 commit f74d072

File tree

2 files changed

+41
-32
lines changed

2 files changed

+41
-32
lines changed

src/lib/collection.html

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -106,32 +106,38 @@
106106
},
107107

108108
_applySplices: function(splices) {
109-
var keySplices = [];
110-
for (var i=0; i<splices.length; i++) {
111-
var j, o, key, s = splices[i];
112-
// Removed keys
113-
var removed = [];
114-
for (j=0; j<s.removed.length; j++) {
115-
o = s.removed[j];
116-
key = this.remove(o);
109+
// Dedupe added and removed keys to a final added/removed map
110+
var keyMap = {}, key, i;
111+
splices.forEach(function(s) {
112+
s.addedKeys = [];
113+
for (i=0; i<s.removed.length; i++) {
114+
key = this.getKey(s.removed[i]);
115+
keyMap[key] = keyMap[key] ? null : -1;
116+
}
117+
for (i=0; i<s.addedCount; i++) {
118+
var item = this.userArray[s.index + i];
119+
key = this.getKey(item);
120+
key = (key === undefined) ? this.add(item) : key;
121+
keyMap[key] = keyMap[key] ? null : 1;
122+
s.addedKeys.push(key);
123+
}
124+
}, this);
125+
// Convert added/removed key map to added/removed arrays
126+
var removed = [];
127+
var added = [];
128+
for (var key in keyMap) {
129+
if (keyMap[key] < 0) {
130+
this.removeKey(key);
117131
removed.push(key);
118132
}
119-
// Added keys
120-
var added = [];
121-
for (j=0; j<s.addedCount; j++) {
122-
o = this.userArray[s.index + j];
123-
key = this.add(o);
133+
if (keyMap[key] > 0) {
124134
added.push(key);
125135
}
126-
// Record splice
127-
keySplices.push({
128-
index: s.index,
129-
removed: removed,
130-
removedItems: s.removed,
131-
added: added
132-
});
133136
}
134-
return keySplices;
137+
return [{
138+
removed: removed,
139+
added: added
140+
}];
135141
}
136142

137143
};

src/lib/template/dom-repeat.html

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,13 @@
268268
this._error(this._logf('dom-repeat', 'expected array for `items`,' +
269269
' found', this.items));
270270
}
271-
this._splices = [];
271+
this._keySplices = [];
272+
this._indexSplices = [];
272273
this._needFullRefresh = true;
273274
this._debounceTemplate(this._render);
274275
} else if (change.path == 'items.splices') {
275-
this._splices = this._splices.concat(change.value.keySplices);
276+
this._keySplices = this._keySplices.concat(change.value.keySplices);
277+
this._indexSplices = this._indexSplices.concat(change.value.indexSplices);
276278
this._debounceTemplate(this._render);
277279
} else { // items.*
278280
// slice off 'items.' ('items.'.length == 6)
@@ -303,10 +305,10 @@
303305
},
304306

305307
/**
306-
* Forces the element to render its content. Normally rendering is
307-
* asynchronous to a provoking change. This is done for efficiency so
308-
* that multiple changes trigger only a single render. The render method
309-
* should be called if, for example, template rendering is required to
308+
* Forces the element to render its content. Normally rendering is
309+
* asynchronous to a provoking change. This is done for efficiency so
310+
* that multiple changes trigger only a single render. The render method
311+
* should be called if, for example, template rendering is required to
310312
* validate application state.
311313
*/
312314
render: function() {
@@ -324,17 +326,18 @@
324326
this._needFullRefresh = false;
325327
} else {
326328
if (this._sortFn) {
327-
this._applySplicesUserSort(this._splices);
329+
this._applySplicesUserSort(this._keySplices);
328330
} else {
329331
if (this._filterFn) {
330332
// TODK(kschaaf): Filtering using array sort takes slow path
331333
this._applyFullRefresh();
332334
} else {
333-
this._applySplicesArrayOrder(this._splices);
335+
this._applySplicesArrayOrder(this._indexSplices);
334336
}
335337
}
336338
}
337-
this._splices = [];
339+
this._keySplices = [];
340+
this._indexSplices = [];
338341
// Update final _keyToInstIdx and instance indices
339342
var keyToIdx = this._keyToInstIdx = {};
340343
for (var i=0; i<this._instances.length; i++) {
@@ -511,10 +514,10 @@
511514
}
512515
this._instances.splice(s.index, s.removed.length);
513516
// Insert placeholders for new rows
514-
for (var i=0; i<s.added.length; i++) {
517+
for (var i=0; i<s.addedKeys.length; i++) {
515518
var inst = {
516519
isPlaceholder: true,
517-
key: s.added[i]
520+
key: s.addedKeys[i]
518521
};
519522
this._instances.splice(s.index + i, 0, inst);
520523
}

0 commit comments

Comments
 (0)