2013-11-21 3 views
8

मैंने एनजी-दोहराया और कोड ब्लॉक को निकाला, यह देखते हुए कि एल्गोरिदम को दोहराते हुए तर्क शामिल है (जिसे मैं समझना चाहता हूं कि यह कैसे काम करता है)।एनजी-दोहराना कैसे काम करता है?

मेरे पास कुछ प्रश्न हैं, लेकिन चूंकि वे एनजी-दोहराने के आंतरिक के बारे में हैं, इसलिए मैंने उनसे उनसे पूछना चुना। मुझे उन्हें अलग-अलग SO प्रश्नों में अलग करने का कोई कारण नहीं दिख रहा है। मैंने प्रत्येक प्रश्न को संदर्भित कोड की कौन सी पंक्ति (रेखा) के लिए इनलाइन चिह्नित की है।

  1. क्यों वे यह सुनिश्चित करें कि trackById देशी hasOwnProperty कार्य नहीं है बनाने के लिए की जरूरत है? (यही वह है जो assertNotHasOwnProperty फ़ंक्शन करता है, कोणीय के आंतरिक एपीआई का हिस्सा)
  2. जहां तक ​​मेरा अंतर्ज्ञान जाता है, यह कोड पहले से ही पुनरावर्तक में आइटम पर निष्पादित होता है, जब इसे संग्रह को अपडेट करना होता है - यह सिर्फ उन्हें उठाता है और उन्हें धक्का देता है प्रसंस्करण के लिए सूची में, सही?
  3. यह कोड ब्लॉक पुनरावर्तक संग्रह में डुप्लिकेट की तलाश करता है। लेकिन यह वास्तव में ऐसा करता है जो मेरे बाहर है। कृपया समझाएँ।
  4. कोणीय को nextBlockOrder में nextBlockMapऔर दोनों ब्लॉक ऑब्जेक्ट को स्टोर करना क्यों है?
  5. block.endNode और block.startNode क्या हैं?
  6. मुझे लगता है कि उपर्युक्त प्रश्न का उत्तर यह बताएगा कि यह एल्गोरिदम कैसे काम करता है, लेकिन कृपया यह बताने की ज़रूरत है कि nextNode'$$NG_REMOVED' है या नहीं?
  7. यहां क्या होता है? दोबारा, मुझे लगता है कि प्रश्न 6 पहले से ही इसका जवाब देगा। लेकिन अभी भी यह इंगित कर रहा है।

जैसा कि मैंने कहा था, मैंने कोड को दोहराने के लिए दोहराए गए कोड को खोजने के लिए दोहराना दोहराया है। इसके अलावा, मैं बाकी निर्देश को समझता हूं। तो आगे की हलचल के बिना, यहाँ कोड (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; 

उत्तर

10

निर्देश के साथ कुछ फेरबदल के बाद, मैं ng-repeater रों कोड से परिचित हो गया, और मेरे कुछ प्रश्नों का उत्तर में कामयाब रहे। मैं बोल्ड चीजों में प्रकाश डाला मैं अभी तक अपने दम पर यह पता लगाने नहीं कर सकता है, और अगर किसी को भी बोल्ड भागों पर कुछ प्रकाश डाला सकता है की सराहना करेंगे:

  1. आईडी hasOwnProperty के लिए परीक्षण किया जाता है, क्योंकि वे यह विधि यह जांचने के लिए करें कि आईडी पुनरावृत्ति वस्तुओं में मौजूद है या नहीं (lastBlockMap, nextBlockMap) (यह प्रक्रिया नीचे बताई गई है)। हालांकि, यह पता नहीं लगा कि यह वास्तव में क्या परिदृश्य हो सकता है।
  2. मैं अपनी धारणा में सही था। nextBlockMap में वे सभी आइटम शामिल हैं जिन्हें वर्तमान मॉडल परिवर्तन पर स्थानांतरित किया जाएगा। lastBlockMap में पिछले मॉडल अद्यतन से सबकुछ शामिल है। यह संग्रह में डुप्लीकेट खोजने के लिए प्रयोग किया जाता है।
  3. ठीक है, यह वास्तव में बहुत सरल है। इस for लूप में, ng-repeat को lastBlockMap से आइटम भरता है।if के आदेश को देखते हुए, यह देखना आसान है कि यदि आइटम lastBlockMap में नहीं पाया जा सकता है, लेकिन यह पहले से ही nextBlockMap में मौजूद है (यानी, यह पहले से ही से कॉपी किया गया था, और इसलिए संग्रह में trackById दो बार दिखाई देता है) - यह एक डुप्लिकेट है। forEach क्या nextBlockMap (block एस में सभी प्रारंभिक आइटमों के माध्यम से चलाया जाता है जिसमें startNode संपत्ति होती है) और उनके आईडी को lastBlockMap पर वापस धक्का दें। हालांकि मैं समझ नहीं पा रहा हूं कि यह क्यों जरूरी है।
  4. एकमात्र कारण मैं (एक trackById हैश में सभी block वस्तुओं) nextBlockMap से अलग होने के nextBlockOrder (एक सरणी में सभी trackById रों) के लिए मिल सकता है, इस लाइन है, जो एक सरणी के साथ काम कर यह एक आसान और सरल ऑपरेशन बनाता है: if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;। यह प्रश्न 5 और 6:
  5. block.startNode और block.endNode के जवाब में समझाया गया है, एकत्रित होने वाले आइटम में से संबंधित ब्लॉक से पहले और अंतिम डोम नोड्स हैं। इसलिए, यह पंक्ति दोहराना में पिछले आइटम के अंतिम DOM नोड को संदर्भित करने के लिए previousNode सेट करती है।
  6. previousNode तब एक लूप में पहले नोड के रूप में उपयोग किया जाता है जो यह जांचता है कि आइटम्स को स्थानांतरित करने या दोहराने वाले संग्रह से हटा दिए जाने पर डोम कैसे बदलता है - फिर, केवल अगर हम सरणी में पहले ब्लॉक के साथ काम नहीं कर रहे हैं ।
  7. यह आसान है - यह ब्लॉक को प्रारंभ करता है - बाद में संदर्भ के लिए $scope और startNode और endNode असाइन करना, और nextBlockMap में सबकुछ बचाता है। क्लोन तत्व के ठीक बाद बनाई गई टिप्पणी, यह गारंटी देने के लिए है कि हमारे पास हमेशा endNode है।
संबंधित मुद्दे