Angular如何在$digest循环后更新视图

How does Angular update the view after a $digest cycle?

本文关键字:循环 更新 新视图 digest Angular      更新时间:2023-09-26

是否:

1) 运行DOM(从ng-app开始),如果它看到一个带有指令的DOM节点,则使用相应的模型值更新该DOM节点。

2) 在运行$$watchers列表时,如果它检测到更改,它会引用需要更新的DOM节点,所以它只是这样做(因此,使用这种方法,它不会运行整个DOM,而是存储并使用对$$watchers中节点的引用)。

这更多的是第二种方法。

Angular通过指令完成所有繁重的工作。你在Angular中使用的几乎所有东西都是一个指令:

<div ng-app>
<div ng-controller>
<button ng-click>
<!-- input is actually a directive -->
<input ng-model="foo" />

所有这些小指令都获得了对它们所附加的DOM元素的引用,以及一个$scope对象指令只是注册一个回调,以便在发生更改时执行

正如您已经注意到的,这些被称为观察者

作用域是分层次的,所以总是有一个相关对象树组成应用程序状态。当$digest循环开始时,它递归地遍历该树以寻找更改,并启动回调(也称为观察者)

然后回调可以选择执行它想要的任何操作。只是在大多数情况下,它是在更新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>