什么被认为是Angular的观察者?

时间:2015-08-03 17:49:47

标签: javascript angularjs watch angularjs-watch

考虑什么" watchers"在Angular?观察者本身是观察者的唯一类型,还是其他角色结构,如ngModel观察者?

或者我错过了大局?例如,观察者是什么使ngModel等指令能够起作用?

更新:有没有办法判断何时存在观察者?在测试中,我想知道何时调用范围。$ digest()

3 个答案:

答案 0 :(得分:2)

  

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名观察者的。我们只能看到3,实际上我们已经使用ng-showng-if指令在内部将$watch放在其属性值中提供的表达式上。 &安培;这些表达式在每个摘要周期进行评估。

  

您还可以使用创建自定义观察程序   $watch(深度/简单观察)&amp; $watchGroup

此外,您可以让观察者使用$attrs.$observe,这与手表的作用相同,但它是唯一的特殊功能,它适用于插值变量。

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

大多数angular指令在内部使用观察者,如ng-repeatng-showng-ifng-includeng-switchng-bind,插值指令{ {1}},过滤器等。他们在内部设置了监视双向绑定的东西。

答案 1 :(得分:1)

观察者(如果我们仅采用您所基于的文档)是角度机制,旨在以任何角度摘要周期在双向绑定样式中观察变量或函数结果;而且无论摘要周期的触发事件是什么。

我会称“观察者”任何角度机制能够根据可能发生的 ANY事件触发某些代码。

通常,要创建观察者,您应该使用:$scope.watch(...)

请注意,只要可以,最好避免使用观察者 实际上,他们的回调将在每个消化周期触发,以执行脏检查;经常影响表现。

ng-model与观察者的概念无关  ng-model只是将一些变量从视图绑定到控制器的一种方法 它们是两个截然不同的概念。

答案 2 :(得分:1)

为了说明$ 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.time变量内部创建一个监视。

该示例还包含两个按钮。第一个按钮附有一个ng-click侦听器。单击该按钮时,将调用$ scope.updateTime()函数,然后在AngularJS调用$ scope。$ digest()以便更新数据绑定。

第二个按钮从控制器函数内部获取一个标准的JavaScript事件监听器。单击第二个按钮时,将执行侦听器功能。如您所见,两个按钮的侦听器函数几乎相同,但是当调用第二个按钮的侦听器函数时,不会更新数据绑定。这是因为在执行第二个按钮的事件侦听器后,不会调用$ scope。$ digest()。因此,如果单击第二个按钮,则会在$ scope.data.time变量中更新时间,但永远不会显示新时间。

要解决这个问题,我们可以在按钮事件监听器的最后一行添加$ scope。$ digest()调用,如下所示:

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

您可以使用$ apply()函数,而不是在按钮侦听器函数中调用$ digest():

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

注意如何从按钮事件侦听器内部调用$ scope。$ apply()函数,以及如何在作为参数传递给$ apply()的函数内执行$ scope.data.time变量的更新功能。当$ apply()函数调用完成时,AngularJS会在内部调用$ digest(),因此所有数据绑定都会更新。