考虑什么" watchers"在Angular?观察者本身是观察者的唯一类型,还是其他角色结构,如ngModel
观察者?
或者我错过了大局?例如,观察者是什么使ngModel
等指令能够起作用?
更新:有没有办法判断何时存在观察者?在测试中,我想知道何时调用范围。$ digest()
答案 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>
在上面的代码中猜猜有多少观察者,你可以看到有3个{{}}
插值指令将放在观察者数组中然后如果你在控制台$scope.$$watchers
中看到它会显示5位观察者。
它是如何显示5名观察者的。我们只能看到3,实际上我们已经使用ng-show
和ng-if
指令在内部将$watch
放在其属性值中提供的表达式上。 &安培;这些表达式在每个摘要周期进行评估。
您还可以使用创建自定义观察程序
$watch
(深度/简单观察)&amp;$watchGroup
此外,您可以让观察者使用$attrs.$observe
,这与手表的作用相同,但它是唯一的特殊功能,它适用于插值变量。
$attrs.$observe('test',function(value){
alert('')
});
大多数angular指令在内部使用观察者,如ng-repeat
,ng-show
,ng-if
,ng-include
,ng-switch
,ng-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(),因此所有数据绑定都会更新。