Why does ng-repeat reorder the communication function

The usual procedure for executing the compilation function and nested directive links below

Markup

<dir1>
  <div dir2="">
  </div>
</dir1>

Execution order

1) compile of directive 1
2) compile of directive 2
3) link of directive 2
4) link of directive 1

Assuming it dir1has a property restrictset to 'E', and dir2has restrictset to'A'

Now, if you use the directive ng-repeatin the same markup, the order in which the changes are made

Markup

<dir1>
  <div ng-repeat="item in items">
    <div dir2="">
    </div>
  </div>
</dir1>

Assuming it is itemsdefined in scope, the execution order changes to

1) compile of directive 1
2) link of directive 1
3) compile of directive 2
4) link of directive 2

Plunker - https://plnkr.co/edit/fRGHS1Bqu3rrY5NW2d97?p=preview

? , ng-repeat transclude, element. , dir1, ng-repeat.

.

+4
1

, ! angular webapps, .

, ngRepeat google $scope. $watchCollection, . ( .) $watchCollection setTimeout .

ngRepeat. myRepeat.

//mock ng-repeat : )
app.directive('myRepeat', function ($compile) {
    return {
        restrict:'A',
        transclude: 'element',
        priority: 1000,
        terminal: true,
        $$tlb: true,
        compile: function ($element, $attr) {
            var expression = $attr.myRepeat;
            var ngRepeatEndComment = $compile.$$createComment('end myRepeat', expression);

            //parse the ngRepeat expressions.
            var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);


            var rhs = match[2]; //this would get items in your example

            return function ($scope, $element, $attr, ctrl, $transclude) {

                //$watch $scope[rhs] which rhs would be items in your example.

                $scope.$watchCollection(rhs, function myRepeatAction(collection) {
                  $transclude(function(clone, scope) {

                    clone[clone.length++] = clone; //append element
                  });

                });   
            }
        }
    }
});

watchCollection, . $watchCollection setTimeout, .

angular.js, watchCollection => $watch => $evalAsync => $browser.defer => setTimeout

$ .

$source.defer

, .:)

myRepeat. github angular.js.

P.S , angular - 1.5.3, 1.5.3.


async

setTimeout.

, ,

function dir1(callback) {

   console.log('compile dir1');
   callback();
   console.log('link dir1');
}

function dir2() {
   console.log('compile dir2');
   console.log('link dir2');
}

dir1(dir2);
//compile dir1
//compile dir2
//link dir2
//link dir1

ngRepeat, ,

function dir1(callback) {
   console.log('compile dir1');
   callback();
   console.log('link dir1');
}

function dir2() {
   console.log('compile dir2');
   console.log('link dir2');
}
function myRepeat(callback) {
   return function() {
       setTimeout(callback, 0);
   }
}

dir1(myRepeat(dir2));
//compile dir1
//link dir1
//compile dir2
//link dir2

, 2. , ?

setTimeout ( 0).

, ,, , link dir1.

1. compile dir1
2. setTimeout(execute after 0 second)
3. link dir1(current block is running, so do this first) 
4. compile dir2 (it free now, invoke the callback)
5. link dir2

, . setTimeout John Resig javascript.

+4

All Articles