Skip to content

Commit acec8ef

Browse files
committed
Update existing nodes by matching cells
1 parent 8590b9b commit acec8ef

File tree

1 file changed

+55
-36
lines changed

1 file changed

+55
-36
lines changed

src/components/virtual-scroll/virtual-util.ts

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -121,73 +121,81 @@ export function populateNodeData(startCellIndex: number, endCellIndex: number, s
121121
initialLoad: boolean): boolean {
122122
if (!records || records.length === 0) {
123123
nodes.length = 0;
124+
viewContainer.clear();
124125
return true;
125126
}
126127
const recordsLength = records.length;
127128

128129
let hasChanges = false;
129-
let node: VirtualNode;
130+
// let node: VirtualNode;
130131
let availableNode: VirtualNode;
131132
let cell: VirtualCell;
132133
let viewInsertIndex: number = null;
133134
let totalNodes = nodes.length;
134135
let templateRef: TemplateRef<VirtualContext>;
135136
startCellIndex = Math.max(startCellIndex, 0);
136137
endCellIndex = Math.min(endCellIndex, cells.length - 1);
138+
console.log(initialLoad);
137139

140+
const usedNodes: any[] = [];
138141
for (var cellIndex = startCellIndex; cellIndex <= endCellIndex; cellIndex++) {
139142
cell = cells[cellIndex];
140143
availableNode = null;
141144

142145
// find the first one that's available
143-
if (!initialLoad) {
144-
const existingNode = nodes.find(n => n.cell === cellIndex);
145-
if (existingNode) {
146-
if (existingNode.view.context.$implicit === records[existingNode.cell]) continue; // optimization: node data is the same no need to update
147-
availableNode = existingNode; // update existing node
148-
} else {
149-
for (var i = 0; i < totalNodes; i++) {
150-
node = nodes[i];
151-
152-
if (cell.tmpl !== node.tmpl || i === 0 && cellIndex !== 0) {
153-
// the cell must use the correct template
154-
// first node can only be used by the first cell (css :first-child reasons)
155-
// this node is never available to be reused
156-
continue;
157-
}
146+
// if (!initialLoad) {
147+
const existingNode = nodes.find(n => n.cell === cellIndex && n.tmpl === cell.tmpl);
148+
if (existingNode) {
149+
console.debug('virtual-util', 'found that cell is already rendered in existingNode', existingNode);
150+
if (existingNode.view.context.$implicit === records[cell.record]) {
151+
usedNodes.push(existingNode);
152+
continue; // optimization: node data is the same no need to update
153+
}
154+
console.debug('virtual-util', 'data is not the same, will need to update node. Setting as available node');
155+
availableNode = existingNode; // update existing node
156+
} else {
157+
console.debug('virtual-util', 'cell was not rendered in current nodes, will now look for an available node');
158+
for (var i = 0; i < totalNodes; i++) {
159+
const node = nodes[i];
160+
161+
if (cell.tmpl !== node.tmpl || i === 0 && cellIndex !== 0) {
162+
// the cell must use the correct template
163+
// first node can only be used by the first cell (css :first-child reasons)
164+
// this node is never available to be reused
165+
continue;
166+
}
158167

159-
if (node.cell < startCellIndex || node.cell > endCellIndex) {
160-
161-
if (!availableNode) {
162-
// havent gotten an available node yet
163-
availableNode = nodes[i];
164-
break;
165-
} else if (scrollingDown) {
166-
// scrolling down
167-
if (node.cell < availableNode.cell) {
168-
availableNode = nodes[i];
169-
break;
170-
}
171-
172-
} else {
173-
// scrolling up
174-
if (node.cell > availableNode.cell) {
175-
availableNode = nodes[i];
176-
break;
177-
}
168+
if (node.cell < startCellIndex || node.cell > endCellIndex) {
169+
170+
if (!availableNode) {
171+
// havent gotten an available node yet
172+
availableNode = node;
173+
console.debug('virtual-util', 'found node to reuse', availableNode);
174+
} else if (scrollingDown) {
175+
// scrolling down
176+
if (node.cell < availableNode.cell) {
177+
availableNode = node;
178+
console.debug('virtual-util', 'scrolling-down found better node to reuse', availableNode);
179+
}
180+
} else {
181+
// scrolling up
182+
if (node.cell > availableNode.cell) {
183+
availableNode = node;
184+
console.debug('virtual-util', 'scrolling-up found better node to reuse', availableNode);
178185
}
179186
}
180187
}
181188
}
182189
}
190+
// }
183191

184192
if (!availableNode) {
185193
// did not find an available node to put the cell data into
186194
// insert a new node after existing ones
187195
if (viewInsertIndex === null) {
188196
viewInsertIndex = -1;
189197
for (var j = totalNodes - 1; j >= 0; j--) {
190-
node = nodes[j];
198+
const node = nodes[j];
191199
if (node) {
192200
viewInsertIndex = viewContainer.indexOf(node.view);
193201
break;
@@ -212,6 +220,7 @@ export function populateNodeData(startCellIndex: number, endCellIndex: number, s
212220
};
213221

214222
totalNodes = nodes.push(availableNode);
223+
console.warn('virtual-util', '++++++++ did not find a node to reuse, created a new one', availableNode);
215224
}
216225

217226
// assign who's the new cell index for this node
@@ -225,8 +234,18 @@ export function populateNodeData(startCellIndex: number, endCellIndex: number, s
225234
availableNode.hasChanges = true;
226235
availableNode.lastTransform = null;
227236
hasChanges = true;
237+
usedNodes.push(availableNode);
228238
}
229239

240+
const unusedNodes = nodes.filter(n => usedNodes.indexOf(n) < 0);
241+
unusedNodes.forEach(node => {
242+
const index = viewContainer.indexOf(node.view);
243+
viewContainer.remove(index);
244+
const removeIndex = nodes.findIndex(n => n === node);
245+
nodes.splice(removeIndex, 1);
246+
console.warn('virtual-util', '-------- found orphan node, removing', node);
247+
});
248+
230249
return hasChanges;
231250
}
232251

0 commit comments

Comments
 (0)