在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-show
和ng-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(),这样所有的数据绑定都会被更新。