我剖析了ng-repeat并提取了附加的代码块,看到它们包含处理 重复 算法的逻辑(我想了解它的工作原理)。
我有很多问题,但是由于它们都是关于ng- repeat的内部结构,因此我选择在这里全部询问。我看不出有任何理由将它们分为不同的SO问题。我已标记内联每个问题所指向的代码行。
trackById
hasOwnProperty
assertNotHasOwnProperty
nextBlockMap
nextBlockOrder
block.endNode
block.startNode
nextNode
'$$NG_REMOVED'
就像我说的那样,我通过ng- repeat进行了查找,找到了我认为与重复机制相关的代码。另外,我确实了解该指令的其余部分。因此,事不宜迟,这是代码(来自v1.2.0):
length = nextBlockOrder.length = collectionKeys.length; for (index = 0; index < length; index++) { key = (collection === collectionKeys) ? index : collectionKeys[index]; value = collection[key]; trackById = trackByIdFn(key, value, index); // question #1 assertNotHasOwnProperty(trackById, '`track by` id'); // question #2 if (lastBlockMap.hasOwnProperty(trackById)) { block = lastBlockMap[trackById]; delete lastBlockMap[trackById]; nextBlockMap[trackById] = block; nextBlockOrder[index] = block; // question #3 } else if (nextBlockMap.hasOwnProperty(trackById)) { // restore lastBlockMap forEach(nextBlockOrder, function(block) { if (block && block.startNode) lastBlockMap[block.id] = block; }); // This is a duplicate and we need to throw an error throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}", expression, trackById); // question #4 } else { // new never before seen block nextBlockOrder[index] = { id: trackById }; nextBlockMap[trackById] = false; } } for (index = 0, length = collectionKeys.length; index < length; index++) { key = (collection === collectionKeys) ? index : collectionKeys[index]; value = collection[key]; block = nextBlockOrder[index]; // question #5 if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode; if (block.startNode) { // if we have already seen this object, then we need to reuse the // associated scope/element childScope = block.scope; // question #6 nextNode = previousNode; do { nextNode = nextNode.nextSibling; } while(nextNode && nextNode[NG_REMOVED]); if (block.startNode != nextNode) { // existing item which got moved $animate.move(getBlockElements(block), null, jqLite(previousNode)); } previousNode = block.endNode; } else { // new item which we don't know about childScope = $scope.$new(); } // question #7 if (!block.startNode) { linker(childScope, function(clone) { clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' '); $animate.enter(clone, null, jqLite(previousNode)); previousNode = clone; block.scope = childScope; block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0]; block.endNode = clone[clone.length - 1]; nextBlockMap[block.id] = block; }); } } lastBlockMap = nextBlockMap;
在修改了该指令之后,我开始熟悉ng-repeaters代码,并设法回答了我的一些问题。我以 粗体 突出显示了我自己还无法解决的问题,如果有人可以对 粗体 部分有所了解,我将不胜感激:
ng-repeater
lastBlockMap
for
ng-repeat
if
forEach
block
startNode
if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;
previousNode
$scope
endNode