Angular的$ watch函数允许在指定的属性更改时触发事件,如下所示。在范围内发生任何更改时,是否有类似的方式来侦听事件?
// works
$scope.$watch("someval", function() { }, true);
$scope.$watch(function(scope){ return scope.someval; }, function() { }, true);
// doesn't work
$scope.$watch("this", function() { }, true);
$scope.$watch(function(scope){ return scope; }, function() { }, true);
答案 0 :(得分:24)
我相信你不能注意$scope
的变化(除了使用@ ValentynShybanov的消化)。你最接近的事情是观察摘要电话:
$scope.$watch(function() {
console.log("digest called");
});
每次在作用域上调用$digest
时,都会调用上述函数,即使作用域的属性没有更改,也会调用
答案 1 :(得分:9)
这不是直截了当的,因为范围是一个普通的对象。这是Backbone,您可以订阅所有事件,但为此您的模型应扩展专有接口 - Backbone.Model
。 Angular将观察者模式放在它的经典外观中。这是一个不寻常的设计决定。基本上有一个循环,其中Angular评估被监视的表达式,当它检测到与前一次迭代的差异时,它会通知观察者。一个非常有趣的方法,可能是观察者模式的唯一替代方法(除了反应式编程,这还不常见)。
我建议使用一个函数作为监视表达式,它返回范围的哈希值。不幸的是,范围包含某些地方的循环引用,因此像JSON.stringify($scope)
这样的快速解决方案不起作用。我写了快速而肮脏的概念证明。 http://jsfiddle.net/ADukg/2544。无论您输入什么文本字段,它都会打印到控制台。字符串哈希函数取自Generate a Hash from string in Javascript/jQuery。
function MyCtrl($scope) {
$scope.$watch(
function($scope) {return hash($scope);},
function() {console.log("changed");}
);
}
答案 2 :(得分:3)
我自己遇到了这个问题,我用与@ ValentynShybanov的评论类似的东西解决了这个问题,但并不完全相同。 我的解决方案不要求您按照评论中的说明为所有属性添加前缀。
var entireScope = {};
for ( var i in $scope ){
if ( i[0] !== '$' && i !== 'this' && i !== 'constructor'){
console.log(i);
entireScope[i] = $scope[i];
}
}
$scope.entireScope = entireScope;
$scope.$watch('entireScope', function( newValue, oldValue ){
$log.info('entireScope has changed',newValue, oldValue);
}, true);
正如您所看到的解决方案完全相同,但实际上它为范围添加了另一个属性,而不是替换您已有的结构。这个新属性代表整个范围(因此它的名字),你可以观看它。
我写的循环可能过于通用,您可以使用自定义初始化替换它。例如:
$scope.entireScope = { 'someVal' : $scope.someVal }
此解决方案可以满足您的需求,并且无需重构代码。
答案 3 :(得分:2)
一个简单的解决方案可能是您应该只检查范围的变量,但它可能是对象。
<强> app.js 强>
app.controller('MainController', ['$scope', function($scope){
$scope.watchable = {
'param1':'',
'param2':''
};
$scope.update = -1;
$scope.$watch('watchable', function(scope){
scope.update++;
}, true);
});
<强>的index.html 强>
<div ng-controller="MainController">
<input type='text' ng-model="watchable.param1">
<input type='text' ng-model="watchable.param2">
<p>param1:{{watchable.param1}}, param2:{{watchable.param2}}</p>
<p>update:{{update}}
</div>
这里的诀窍是通过&#39; true&#39;在$ watch函数的第三个参数中,它将执行angular.equal检查,该检查是按值检查而不是简单的引用检查。如果正确的话请告诉我。