angularjs – ng-repeat如何工作?
我解剖了ng-repeat并提取了附加的代码块,看到这些代码块包含处理重复算法的逻辑(我想了解它是如何工作的).
我有很多问题,但由于它们都是关于ng-repeat的内部结构,所以我选择在这里问问它们.我认为没有理由将它们分成不同的SO问题.我已经在内联标记了每个问题引用的代码行. >为什么他们需要确保trackById不是本机hasOwnProperty函数? (这就是assertNotHasOwnProperty函数所做的,是Angular内部API的一部分) 就像我说的那样,我挖掘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,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代码,并设法回答了我的一些问题.我粗略地突出了我自己无法弄清楚的事情,如果有人能够对大胆的部分有所了解,我将不胜感激:
>为hasOwnProperty测试ID,因为它们使用该方法检查迭代对象中是否存在ID(lastBlockMap,nextBlockMap)(此过程如下所述).然而,我无法找出实际发生的情况.>我的假设是正确的. nextBlockMap包含将在当前模型更改中转换的所有项目. lastBlockMap包含先前模型更新的所有内容.它用于在集合中查找重复项.>好的,这个实际上很简单.在这个for循环中,ng-repeat用lastBlockMap中的项填充nextBlockMap.查看ifs的顺序,很容易看出如果在lastBlockMap中找不到该项,但它已经存在于nextBlockMap中(意思是,它已经从lastBlockMap复制到那里,因此它的trackById在集合中出现两次) – 这是重复的. forEach执行的操作只是遍历nextBlockMap中的所有初始化项(具有startNode属性的块)并将其ID重新推送到lastBlockMap.但我无法理解为什么这是必要的.>我可以找到将nextBlockOrder(数组中的所有trackByIds)与nextBlockMap(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. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |