Skip to content

Commit af155ca

Browse files
committed
refactor(ngRepeat): simplify the code
This re-introduce the PR dart-archive#1018: "refactor(ng-repeat): refactor fix for dart-archive#1015" which had been reverted.
1 parent 30cea03 commit af155ca

File tree

1 file changed

+60
-85
lines changed

1 file changed

+60
-85
lines changed

Diff for: lib/directive/ng_repeat.dart

+60-85
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class NgRepeat {
8383
String _valueIdentifier;
8484
String _keyIdentifier;
8585
String _listExpr;
86-
List<_Row> _rows;
86+
List<View> _views;
8787
Function _generateId = (key, value, index) => value;
8888
Watch _watch;
8989

@@ -131,109 +131,95 @@ class NgRepeat {
131131
_watch = _scope.watch(
132132
_listExpr,
133133
(changes, _) {
134-
_onChange((changes is CollectionChangeRecord) ? changes : null);
134+
if (changes is CollectionChangeRecord && changes != null) {
135+
_onCollectionChange(changes);
136+
} else if (_views != null) {
137+
_views.forEach(_viewPort.remove);
138+
_views = null;
139+
}
135140
},
136141
collection: true,
137142
formatters: formatters
138143
);
139144
}
140145

141-
// Computes and executes DOM changes when the item list changes
142-
void _onChange(CollectionChangeRecord changes) {
143-
final iterable = (changes == null) ? const [] : changes.iterable;
144-
final int length = (changes == null) ? 0 : changes.length;
145-
final rows = new List<_Row>(length);
146+
void _onCollectionChange(CollectionChangeRecord changes) {
147+
final int length = changes.length;
148+
final views = new List<View>(length);
146149
final changeFunctions = new List<Function>(length);
147150
final removedIndexes = <int>[];
148-
final int domLength = _rows == null ? 0 : _rows.length;
151+
final int domLength = _views == null ? 0 : _views.length;
149152
final leftInDom = new List.generate(domLength, (i) => domLength - 1 - i);
150153
var domIndex;
151154

152-
var addRow = (int index, value, View previousView) {
153-
var childContext = _updateContext(new PrototypeMap(_scope.context), index,
154-
length)..[_valueIdentifier] = value;
155-
var childScope = _scope.createChild(childContext);
156-
var view = _boundViewFactory(childScope);
157-
var nodes = view.nodes;
158-
rows[index] = new _Row(_generateId(index, value, index))
159-
..view = view
160-
..scope = childScope
161-
..nodes = nodes
162-
..startNode = nodes.first
163-
..endNode = nodes.last;
164-
_viewPort.insert(view, insertAfter: previousView);
165-
};
155+
Function addFn, moveFn, removeFn;
166156

167-
// todo(vicb) refactor once GH-774 gets fixed
168-
if (_rows == null) {
169-
_rows = new List<_Row>(length);
170-
for (var i = 0; i < length; i++) {
171-
changeFunctions[i] = (index, previousView) {
172-
addRow(index, iterable.elementAt(i), previousView);
173-
};
174-
}
157+
if (_views == null) {
158+
addFn = changes.forEachItem;
159+
moveFn = (_) {};
160+
removeFn = (_) {};
175161
} else {
176-
if (changes == null) {
177-
_rows.forEach((row) {
178-
_viewPort.remove(row.view);
179-
});
180-
leftInDom.clear();
181-
} else {
182-
changes.forEachRemoval((CollectionChangeItem removal) {
183-
var index = removal.previousIndex;
184-
var row = _rows[index];
185-
_viewPort.remove(row.view);
186-
leftInDom.removeAt(domLength - 1 - index);
187-
});
188-
189-
changes.forEachAddition((CollectionChangeItem addition) {
190-
changeFunctions[addition.currentIndex] = (index, previousView) {
191-
addRow(index, addition.item, previousView);
192-
};
193-
});
194-
195-
changes.forEachMove((CollectionChangeItem move) {
196-
var previousIndex = move.previousIndex;
197-
var value = move.item;
198-
changeFunctions[move.currentIndex] = (index, previousView) {
199-
var previousRow = _rows[previousIndex];
200-
var childScope = previousRow.scope;
201-
var childContext = _updateContext(childScope.context, index, length);
202-
if (!identical(childScope.context[_valueIdentifier], value)) {
203-
childContext[_valueIdentifier] = value;
204-
}
205-
rows[index] = _rows[previousIndex];
206-
// Only move the DOM node when required
207-
if (domIndex < 0 || leftInDom[domIndex] != previousIndex) {
208-
_viewPort.move(previousRow.view, moveAfter: previousView);
209-
leftInDom.remove(previousIndex);
210-
}
211-
domIndex--;
212-
};
213-
});
214-
}
162+
addFn = changes.forEachAddition;
163+
moveFn = changes.forEachMove;
164+
removeFn = changes.forEachRemoval;
215165
}
216166

167+
removeFn((CollectionChangeItem removal) {
168+
var index = removal.previousIndex;
169+
_viewPort.remove(_views[index]);
170+
leftInDom.removeAt(domLength - 1 - index);
171+
});
172+
173+
addFn((CollectionChangeItem addition) {
174+
changeFunctions[addition.currentIndex] = (index, previousView) {
175+
var childContext = _updateContext(new PrototypeMap(_scope.context), index,length)
176+
..[_valueIdentifier] = addition.item;
177+
var childScope = _scope.createChild(childContext);
178+
var view = views[index] = _boundViewFactory(childScope);
179+
_viewPort.insert(view, insertAfter: previousView);
180+
};
181+
});
182+
183+
moveFn((CollectionChangeItem move) {
184+
var previousIndex = move.previousIndex;
185+
var value = move.item;
186+
changeFunctions[move.currentIndex] = (index, moveAfter) {
187+
var previousView = _views[previousIndex];
188+
var childScope = previousView.scope;
189+
var childContext = _updateContext(childScope.context, index, length);
190+
if (!identical(childScope.context[_valueIdentifier], value)) {
191+
childContext[_valueIdentifier] = value;
192+
}
193+
views[index] = _views[previousIndex];
194+
// Only move the DOM node when required
195+
if (domIndex < 0 || leftInDom[domIndex] != previousIndex) {
196+
_viewPort.move(previousView, moveAfter: moveAfter);
197+
leftInDom.remove(previousIndex);
198+
}
199+
domIndex--;
200+
};
201+
});
202+
217203
var previousView = null;
218204
domIndex = leftInDom.length - 1;
219205
for(var targetIndex = 0; targetIndex < length; targetIndex++) {
220206
var changeFn = changeFunctions[targetIndex];
221207
if (changeFn == null) {
222-
rows[targetIndex] = _rows[targetIndex];
208+
views[targetIndex] = _views[targetIndex];
223209
if (domIndex < 0 || leftInDom[domIndex] != targetIndex) {
224-
_viewPort.move(rows[targetIndex].view, moveAfter: previousView);
210+
_viewPort.move(views[targetIndex], moveAfter: previousView);
225211
leftInDom.remove(targetIndex);
226212
}
227213
domIndex--;
228214
// The element has not moved but `$last` and `$middle` might still need to be updated
229-
_updateContext(rows[targetIndex].scope.context, targetIndex, length);
215+
_updateContext(views[targetIndex].scope.context, targetIndex, length);
230216
} else {
231217
changeFn(targetIndex, previousView);
232218
}
233-
previousView = rows[targetIndex].view;
219+
previousView = views[targetIndex];
234220
}
235221

236-
_rows = rows;
222+
_views = views;
237223
}
238224

239225
PrototypeMap _updateContext(PrototypeMap context, int index, int length) {
@@ -248,14 +234,3 @@ class NgRepeat {
248234
..[r'$even'] = index.isEven;
249235
}
250236
}
251-
252-
class _Row {
253-
final id;
254-
Scope scope;
255-
View view;
256-
dom.Element startNode;
257-
dom.Element endNode;
258-
List<dom.Node> nodes;
259-
260-
_Row(this.id);
261-
}

0 commit comments

Comments
 (0)