angularjs – ng-repeat如何工作?

前端之家收集整理的这篇文章主要介绍了angularjs – ng-repeat如何工作?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我解剖了ng-repeat并提取了附加的代码块,看到这些代码块包含处理重复算法的逻辑(我想了解它是如何工作的).

我有很多问题,但由于它们都是关于ng-repeat的内部结构,所以我选择在这里问问它们.我认为没有理由将它们分成不同的SO问题.我已经在内联标记了每个问题引用的代码行.

>为什么他们需要确保trackById不是本机hasOwnProperty函数? (这就是assertNotHasOwnProperty函数所做的,是Angular内部API的一部分)
>就我的直觉而言,这段代码会对已经在转发器中的项目执行,当它必须更新集合时 – 它只是将它们拾取并将它们推入列表进行处理,对吧?
>此代码块显然在转发器集合中查找重复项.但它究竟是如何做到这一点超出了我.请解释.
>为什么Angular必须将块对象存储在nextBlockMap和nextBlockOrder中?
>什么是block.endNode和block.startNode?
>我假设上述问题的答案将阐明该算法的工作原理,但请解释为什么必须检查nextNode是否已经’$$NG_REMOVED’?
>这里发生了什么?同样,我认为问题6已经为这一个提供了答案.但仍然指出了这一点.

就像我说的那样,我挖掘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.

原文链接:https://www.f2er.com/angularjs/142268.html

猜你在找的Angularjs相关文章