pil*_*lau 8 angularjs angularjs-ng-repeat
我解剖了ng-repeat并提取了附加的代码块,看到它们包含处理重复算法的逻辑(我想了解它是如何工作的).
我有很多问题,但由于它们都是关于ng-repeat的内部结构,所以我选择在这里问问它们.我认为没有理由将它们分成不同的SO问题.我已将每个问题引用的代码行标记为内联.
trackById不是本机hasOwnProperty功能?(这就是该assertNotHasOwnProperty函数的功能,是Angular内部API的一部分)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;
Run Code Online (Sandbox Code Playgroud)
pil*_*lau 10
经过一些修改指令后,我熟悉了ng-repeater代码,并设法回答了我的一些问题.我强调了大胆的事情我还不能找出我自己,如果任何人都可以对一些线索将不胜感激大胆部分:
hasOwnProperty,因为它们使用该方法来检查迭代对象中是否存在ID(lastBlockMap,nextBlockMap)(此过程如下所述).然而,我无法找出实际发生的情况.nextBlockMap包含将在当前模型更改中转换的所有项目.lastBlockMap包含先前模型更新中的所有内容.它用于在集合中查找重复项.for循环中,ng-repeat填充nextBlockMap来自的项目lastBlockMap.查看ifs 的顺序,很容易看出如果找不到该项lastBlockMap,但它已经存在nextBlockMap(意味着它已经从那里复制过来lastBlockMap,因此它trackById在集合中出现两次) - 它是重复的.什么forEach确实是简单地通过全部初始化项目运行nextBlockMap(blockS作一个startNode属性),推动其ID回lastBlockMap.但我无法理解为什么这是必要的.nextBlockOrder(trackById数组中的所有s)和nextBlockMap(散列中的所有block对象)的唯一原因trackById是这一行,它使用数组使它变得简单易行:if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;.问题5和6的答案中对此进行了解释:block.startNode并且block.endNode是属于所收集的项目的块中的第一个和最后一个DOM节点被重复.因此,此行设置previousNode为引用转发器中上一项的最后一个DOM节点.previousNode 然后用作第一个节点,在一个循环中检查当项目被移动或从转发器集合中移除时DOM如何改变 - 再次,仅在我们不使用数组中的第一个块的情况下.$scope和startNode和endNode供以后参考,并保存一切nextBlockMap.在克隆元素之后创建的注释,是为了保证我们总是有一个endNode.| 归档时间: |
|
| 查看次数: |
4169 次 |
| 最近记录: |