2015-11-25 3 views
4

ли это:

1) Запуск через DOM (начиная с ng-app), и если он видит узел DOM с директивой, обновления, DOM узел с соответствующим значением модели.

или

2) В управлении через $$watchers списка, если он обнаруживает изменения, он имеет ссылку на DOM-узла он должен обновить, поэтому он просто делает это (так, а не проходит через всю DOM, используя этот подход, он будет хранить и использовать ссылку на узел в $$watchers).

ответ

3

Это скорее второй подход.

Угловой делает все, что нужно, тяжелый подъем через директивы. Практически все, что вы используете в угловому директива:

<div ng-app> 
<div ng-controller> 
<button ng-click> 

<!-- input is actually a directive --> 
<input ng-model="foo" /> 

Все эти маленькие директивы получить ссылку на элемент DOM, к которому они присоединены, а также $scope объекта. Директивы просто регистрируют обратный вызов, который должен выполняться, когда что-то меняется.

Как вы уже отметили, это называется наблюдателями.

Область является иерархической, поэтому всегда существует дерево связанных объектов, которые составляют ваше состояние приложения. Когда начинается цикл $digest, он рекурсивно ходит по дереву, ищущему изменения, и отбрасывает обратные вызовы (aka watchers).

Обратный вызов может затем сделать все, что захочет. Просто в большинстве случаев он обновляет DOM.

В конце дня действительно нет ничего волшебного в том, как это происходит. Просто структура обратных вызовов, которые выполняются, когда что-то меняется.

Вот глупый пример пользовательской директивы, которая регистрирует наблюдателя и обновляет DOM при изменении какого-либо свойства.

(function(){ 
 

 
    function getRandomInt(min, max) { 
 
    return Math.floor(Math.random() * (max - min)) + min; 
 
} 
 
    
 
    function updateValue(){ 
 
    return { 
 
     restrict:'A', 
 
     link: function(scope, elem, attrs){ 
 
     elem.on('click', function(){ 
 
      //You would never actually do this, but 
 
      // it's a demo 
 
      scope[attrs.updateValue] = "rgb(" + 
 
      getRandomInt(0, 255) + "," + 
 
      getRandomInt(0, 255) + "," + 
 
      getRandomInt(0, 255) + ")"; 
 
      
 
      //kick off a digest loop manually 
 
      // this is similar to what a lot of angular 
 
      // directives do. 
 
      scope.$digest(); 
 
     }); 
 
     } 
 
    }; 
 
    } 
 
    
 
    function sillyDomChangeOn(){ 
 
    return { 
 
     restrict:'A', 
 
     link: function(scope, elem, attrs){ 
 
     scope.$watch(attrs.sillyDomChangeOn, function(newVal, oldVal){ 
 
      elem.css('color', newVal); 
 
     }); 
 
     } 
 
    }; 
 
    } 
 
    
 
    angular.module('my-app', []) 
 
    .directive('updateValue', updateValue) 
 
    .directive('sillyDomChangeOn', sillyDomChangeOn); 
 

 
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script> 
 
<!-- Latest compiled and minified CSS --> 
 
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> 
 
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"> 
 

 
<div ng-app="my-app" class="container"> 
 
    <button type="button" class="btn btn-primary" update-value="randomVal">Update Value</button> 
 
    <h3>Value: <code>{{randomVal}}</code></h3> 
 
    <div class="well" silly-dom-change-on="randomVal"> 
 
    <h3>This is just a random DIV</h3> 
 
    <div> 
 
</div>

+1

Спасибо! Теперь, когда вы объяснили это, это имеет смысл, но я изначально забыл о том, как цикл дайджеста связан с директивами. Теперь я понимаю, что он (часто) вызывается внутри директивы, где он имеет доступ к элементу DOM (_that's_ как он обращается к элементу DOM!). Соответствующая ссылка на источник [ngBind] (https://github.com/angular/angular.js/blob/master/src/ng/directive/ngBind.js#L63). –

Смежные вопросы