我剖析了ng-repeat并提取了附加的代码块,看到它们包含处理 重复 算法的逻辑(我想了解它的工作原理)。
我有很多问题,但是由于它们都是关于ng-
repeat的内部结构,因此我选择在这里全部询问。我看不出有任何理由将它们分为不同的SO问题。我已标记内联每个问题所指向的代码行。
trackById
不是本机hasOwnProperty
函数?(这就是该assertNotHasOwnProperty
功能的作用,是Angular内部API的一部分)nextBlockMap
和 在nextBlockOrder
?block.endNode
和block.startNode
?nextNode
has(been)'$$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-repeater
s代码,并设法回答了我的一些问题。我以 粗体
突出显示了我自己还无法解决的问题,如果有人可以对 粗体 部分有所了解,我将不胜感激:
hasOwnProperty
,因为它们使用的方法来检查ID是否存在于迭代的对象(lastBlockMap
,nextBlockMap
)(该过程在下面解释)。 但是,我无法确定在什么情况下会发生这种情况。nextBlockMap
包含在当前模型更改中将被排除的所有项目。lastBlockMap
包含上一次模型更新中的所有内容。它用于在集合中查找重复项。for
循环中,ng-repeat
填充的nextBlockMap
项目lastBlockMap
。查看if
s 的顺序,很容易看到,如果在中找不到该项目lastBlockMap
,但它已经存在于中nextBlockMap
(意味着它已经从中复制了lastBlockMap
,因此trackById
在集合中出现了两次)-它是重复项。什么forEach
确实是简单地通过全部初始化项目运行nextBlockMap
(block
S作一个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
。问题内容: 嗨,我有一个简单的ng-repeat-start和end用例,并且工作正常,当我想添加一个内部ng-repeat时出现了问题。这是我的代码 内部ng-repeat到td元素中不起作用,在检查html源代码时看到ngRepeat注释,但未创建td元素。 我的丑陋的解决方法(假设我知道该向量的大小)是: 问题答案: 从那时起,我不确定是否使用角度1.1.6,并且在1.1.5或1.0.7
问题内容: 我试图了解over 的意义。角度文档提供了以下示例 但是,使用, 有人可以解释。的意义吗?谢谢。 问题答案: 这两个指令的含义相似:它们重复HTML标记。所不同的只是,在您的帮助下,您可以重复几个标签,从标签开始于,再到完成于。 例如,您有下一个代码: 因此,现在我们可以为这些代码添加2个指令。 与: 与和: 因此,现在您可以看到,在第一种情况下,仅使用指令重复,但是在第二种情况下,您
问题内容: 我正在尝试使用数组来过滤并在列表中显示信息。为此,我使用了inbuild 方法。 但是我遇到了错误。 这是我的尝试(我通过过滤) 现场演示 问题答案: AngularJS 默认不包含过滤器。您可以使用angular- filter中的 那个。只包含JavaScript 并在您的应用中添加依赖项: 您的代码应立即生效!我编辑了您的Plunker,使其正常工作。
问题内容: 我正在开发一个页面,我需要在其中显示一些框(使用),其中包含频道信息以及显示位置(城市)。 我面临的问题是当我重复第二遍时: 这应该获得第一个ng-repeat的$ index值,并使用显示频道的位置创建一个新数组。它确实做到了。但是,当我使用此数组应用第二个ng- repeat时,它无法正常工作。 说我的html看起来像这样(PS:我需要使用索引值而不是因为我将这些框放到列中) JS
问题内容: 我有一些虚拟XML文件: 使用此库http://code.google.com/p/x2js/将其转换为json,并转换为变量 Day可以具有任意数量的Job,Job可以嵌套并且包含任意数量的其他Job。 现在使用此代码 我可以列出有效的日期。我希望使用以下代码 我可以列出当天的工作日和最高职位,但这是行不通的。(要列出嵌套的Jobs,将是下一个任务,而不是现在询问该任务)。 那么,如
问题内容: 我想使用父列表(foos)的索引作为子列表(foos.bars)中函数调用的参数。 我发现了有人建议使用$ parent。$ index的帖子,但不是的属性。 如何访问父级的索引? 问题答案: 我的示例代码是正确的,问题出在我的实际代码中。不过,我知道很难找到这样的例子,所以我在回答别人的情况。