在Angular中,什么是观察者?



在Angular中什么是"观察者"?观察者本身是唯一一种类型的观察者吗,还是其他的Angular结构,比如ngModel观察者也是?

还是我错过了大局?例如,监视器是否允许像ngModel这样的指令工作?

update:是否有一种方法可以告诉何时存在观察者?在测试中,我想知道何时调用scope.$digest()

watchers只是脏检查,它跟踪旧值和新值

它们在每个消化循环中都得到评估。它可以是作用域变量的组合,也可以是任何表达式。Angular会在每个摘要周期中收集所有这些监视器,并将其保存在$$watchers数组中。你可以通过在控制器中执行console.log($scope.$watchers)来查看有多少观察者。

标记

<body class="container" ng-controller="myCtrl">
  Hello {{test}}
  I'm test to show $$watchers {{test1}}
  <div ng-show="show">SHowiing this div using ng-show</div>
  <div ng-if="show">SHowiing this div using ng-show</div>
  Watcher is not compulsary that should scope variables {{'1'}}
</body>

Plunkr

猜测上面的代码中有多少观察者,正如你所看到的,有3个{{}}插值指令将放置在观察者数组中,然后如果你在控制台$scope.$$watchers中看到它将显示5个观察者。

怎么会有5个观察者呢?实际上我们已经使用了ng-showng-if指令,它们内部将$watch放在其属性值中提供的表达式上。,这些表达式在每个摘要循环中求值。

您还可以使用$watch(深度/简单表)&$watchGroup

也可以让watcher使用$attrs.$observe,这与watch的工作原理相同,但它唯一的特殊之处在于它适用于插值变量。

$attrs.$observe('test',function(value){
    alert('')
});

大多数angular指令内部使用监视器,如ng-repeat, ng-show, ng-if, ng-include, ng-switch, ng-bind,插值指令{{}},过滤器等。他们把手表放在内部管理双向绑定的东西。

观察者(如果我们只使用你所基于的文档)是一种angular机制,旨在以双向绑定的方式观察任何angular摘要周期中变量或函数的结果;不管消化循环的触发事件是什么。

我会把任何能够基于触发任何可能发生的事件的代码的Angular机制称为"观察者"。

通常,要创建一个监视程序,您应该使用:$scope.watch(...)

请注意,尽量避免观看者。
实际上,它们的回调将在每个摘要周期触发以执行脏检查;通常会影响性能。

ng-model与观察者的概念没有联系。
ng-model只是一种方式绑定一些变量从视图到控制器。

为了说明$watch(), $digest()和$apply()是如何工作的,请看下面的例子:

<div ng-controller="myController">
{{data.time}}
<br/>
<button ng-click="updateTime()">update time - ng-click</button>
<button id="updateTimeButton"  >update time</button>
</div>
<script>
var module = angular.module("myapp", []);
var myController1 = module.controller("myController", function($scope) {
    $scope.data = { time : new Date() };
    $scope.updateTime = function() {
        $scope.data.time = new Date();
    }
    document.getElementById("updateTimeButton")
            .addEventListener('click', function() {
        console.log("update time clicked");
        $scope.data.time = new Date();
    });
});
</script>

这个例子绑定了$scope.data。time变量转换为一个插值指令,该指令会将变量值合并到HTML页面中。这个绑定在$scope.data内部创建了一个监视。时间变量。

示例还包含两个按钮。第一个按钮附带了一个ng-click侦听器。当这个按钮被点击时,$scope. updatetime()函数被调用,之后AngularJS调用$scope.$digest()来更新数据绑定。

第二个按钮从控制器函数内部获得一个附加到它的标准JavaScript事件监听器。当单击第二个按钮时,将执行该侦听器函数。正如您所看到的,两个按钮的侦听器函数的操作几乎相同,但是当调用第二个按钮的侦听器函数时,数据绑定没有更新。这是因为在第二个按钮的事件监听器被执行之后,$scope.$digest()没有被调用。因此,如果单击第二个按钮,时间将在$scope.data中更新。时间变量,但不显示新的时间。

为了解决这个问题,我们可以在按钮事件侦听器的最后一行添加$scope.$digest()调用,如下所示:
document.getElementById("updateTimeButton")
    .addEventListener('click', function() {
console.log("update time clicked");
$scope.data.time = new Date();
$scope.$digest();
});

除了在按钮侦听器函数中调用$digest()之外,您还可以使用$apply()函数,如下所示:

document.getElementById("updateTimeButton")
    .addEventListener('click', function() {
$scope.$apply(function() {
    console.log("update time clicked");
    $scope.data.time = new Date();
});
});

请注意$scope.$apply()函数是如何从按钮事件监听器内部调用的,以及$scope.data的更新是如何进行的。时间变量在函数内部执行,作为参数传递给$apply()函数。当$apply()函数调用完成后,AngularJS会在内部调用$digest(),这样所有的数据绑定都会被更新。

最新更新