short-circuit keys algorithm if no keys changed

This commit is contained in:
Leo Horie 2014-11-28 12:44:43 -05:00
parent b6693c7f06
commit c9c0250f12

View file

@ -127,59 +127,70 @@ var m = (function app(window, undefined) {
var DELETION = 1, INSERTION = 2 , MOVE = 3; var DELETION = 1, INSERTION = 2 , MOVE = 3;
var existing = {}, unkeyed = [], shouldMaintainIdentities = false; var existing = {}, unkeyed = [], shouldMaintainIdentities = false;
for (var i = 0; i < cached.length; i++) { for (var i = 0; i < cached.length; i++) {
if (cached[i] && cached[i].attrs && cached[i].attrs.key != null) { if (cached[i].attrs && cached[i].attrs.key != null) {
shouldMaintainIdentities = true; shouldMaintainIdentities = true;
existing[cached[i].attrs.key] = {action: DELETION, index: i} existing[cached[i].attrs.key] = {action: DELETION, index: i}
} }
} }
if (shouldMaintainIdentities) { if (shouldMaintainIdentities) {
for (var i = 0; i < data.length; i++) { var keysDiffer = false
if (data[i] && data[i].attrs) { if (data.length != cached.length) keysDiffer = true
if (data[i].attrs.key != null) { else for (var i = 0; i < data.length; i++) {
var key = data[i].attrs.key; if (cached[i].attrs && data[i].attrs && cached[i].attrs.key != data[i].attrs.key) {
if (!existing[key]) existing[key] = {action: INSERTION, index: i}; keysDiffer = true
else existing[key] = { break
action: MOVE, }
index: i, }
from: existing[key].index,
element: parentElement.childNodes[existing[key].index] || $document.createElement("div") if (keysDiffer) {
for (var i = 0; i < data.length; i++) {
if (data[i].attrs) {
if (data[i].attrs.key != null) {
var key = data[i].attrs.key;
if (!existing[key]) existing[key] = {action: INSERTION, index: i};
else existing[key] = {
action: MOVE,
index: i,
from: existing[key].index,
element: parentElement.childNodes[existing[key].index] || $document.createElement("div")
}
} }
else unkeyed.push({index: i, element: parentElement.childNodes[i] || $document.createElement("div")})
} }
else unkeyed.push({index: i, element: parentElement.childNodes[i] || $document.createElement("div")})
} }
} var actions = []
var actions = [] for (var prop in existing) actions.push(existing[prop])
for (var prop in existing) actions.push(existing[prop]) var changes = actions.sort(sortChanges);
var changes = actions.sort(sortChanges); var newCached = new Array(cached.length)
var newCached = new Array(cached.length)
for (var i = 0, change; change = changes[i]; i++) { for (var i = 0, change; change = changes[i]; i++) {
if (change.action == DELETION) { if (change.action == DELETION) {
clear(cached[change.index].nodes, cached[change.index]); clear(cached[change.index].nodes, cached[change.index]);
newCached.splice(change.index, 1) newCached.splice(change.index, 1)
} }
if (change.action == INSERTION) { if (change.action == INSERTION) {
var dummy = $document.createElement("div"); var dummy = $document.createElement("div");
dummy.key = data[change.index].attrs.key; dummy.key = data[change.index].attrs.key;
parentElement.insertBefore(dummy, parentElement.childNodes[change.index] || null); parentElement.insertBefore(dummy, parentElement.childNodes[change.index] || null);
newCached.splice(change.index, 0, {attrs: {key: data[change.index].attrs.key}, nodes: [dummy]}) newCached.splice(change.index, 0, {attrs: {key: data[change.index].attrs.key}, nodes: [dummy]})
} }
if (change.action == MOVE) { if (change.action == MOVE) {
if (parentElement.childNodes[change.index] !== change.element && change.element !== null) { if (parentElement.childNodes[change.index] !== change.element && change.element !== null) {
parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null) parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null)
}
newCached[change.index] = cached[change.from]
} }
newCached[change.index] = cached[change.from]
} }
for (var i = 0; i < unkeyed.length; i++) {
var change = unkeyed[i];
parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null);
newCached[change.index] = cached[change.index]
}
cached = newCached;
cached.nodes = new Array(parentElement.childNodes.length);
for (var i = 0, child; child = parentElement.childNodes[i]; i++) cached.nodes[i] = child
} }
for (var i = 0; i < unkeyed.length; i++) {
var change = unkeyed[i];
parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null);
newCached[change.index] = cached[change.index]
}
cached = newCached;
cached.nodes = new Array(parentElement.childNodes.length);
for (var i = 0, child; child = parentElement.childNodes[i]; i++) cached.nodes[i] = child
} }
//end key algorithm //end key algorithm