为啥即使 objectEquality 设置为 true,$watch 也不会触发?
Posted
技术标签:
【中文标题】为啥即使 objectEquality 设置为 true,$watch 也不会触发?【英文标题】:Why is $watch not firing even with objectEquality set to true?为什么即使 objectEquality 设置为 true,$watch 也不会触发? 【发布时间】:2015-03-04 08:48:27 【问题描述】:在下面的代码中,$watch
应该在变量scores
发生变化时执行函数recalculateInfoBox
。但是,它什么也没做。
我已经阅读了将true
添加为 $watch 的第三个变量通常可以解决问题,但在这种情况下 $watch 仍然不会触发。
我还需要进行哪些更改才能触发 $watch?
<html ng-app="mainModule">
<head>
<style type="text/css">
</style>
</head>
<body ng-controller="mainController" >
<div>Scores: <input type="text" ng-model="scores" ng-list style="width:500px" placeholder="Enter comma-separated list..."/></div>
<div>You have scores.length items.</div>
<hr/>
ng-style:
<div ng-style="'width': infoBox.width, 'background-color': infoBox.backgroundColor">
This is the info.
</div>
<button ng-click="infoBox.width = '300px'">small</button>
<button ng-click="infoBox.width = '800px'">large</button>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script>
var mainModule = angular.module('mainModule', []);
function mainController($scope)
$scope.scores = [];
$scope.infoBox = width: '300px', backgroundColor: '#ddd';
var recalculateInfoBox = function ()
console.log('in recalc');
$scope.infoBox.width = '100px';
;
$scope.$watch('scores', 'recalculateInfoBox', true);
</script>
</body>
</html>
【问题讨论】:
另外,使用 ng-list 时不需要对象相等性 【参考方案1】:$scope.$watch
采用回调函数(不是回调函数的名称)。
所以,改成这个应该可以:
var recalculateInfoBox = function ()
console.log('in recalc');
$scope.infoBox.width = '100px';
;
$scope.$watch('scores', recalculateInfoBox, true);
来自the docs:
$watch(watchExpression, listener, [objectEquality]);
注册一个 listener 回调以在任何时候执行 watchExpression 发生变化。
【讨论】:
完美,我的疏忽,现在有效,我猜它与这种语法混淆了,myAppModule.controller('TextController',...
这可能有点令人困惑:)。例如,$watch
的第一个参数可以是 $scope
属性 name 或 javascript 表达式(回调),返回检查更改的值。跨度>
【参考方案2】:
问题不是因为对象相等,而是因为listener 必须是函数引用而不是函数名称。与第一个参数(通常作为字符串提供)的作用域属性评估不同,Angular 甚至不会从作用域评估函数(即使您将方法添加为作用域对象的属性)。
$scope.$watch('scores', 'recalculateInfoBox', true);
应该是
$scope.$watch('scores', recalculateInfoBox, true);
angular.module('app', []).controller('ctrl', function($scope)
$scope.scores = [];
$scope.infoBox =
width: '300px',
backgroundColor: '#ddd'
;
var recalculateInfoBox = function()
console.log(arguments);
$scope.infoBox.width = '100px';
;
$scope.$watch('scores', recalculateInfoBox);
);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div>Scores:
<input type="text" ng-paste="handlePaste($event)" ng-model="scores" ng-list style="width:500px" placeholder="Enter comma-separated list..." />
</div>
<div>You have scores.length items.</div>
<hr/>ng-style:
<div ng-style="'width': infoBox.width, 'background-color': infoBox.backgroundColor">
This is the info.
</div>
<button ng-click="infoBox.width = '300px'">small</button>
<button ng-click="infoBox.width = '800px'">large</button>
</div>
在处理 ng-list 时,您甚至可能不需要对象相等性,即 $scope.$watch('scores', recalculateInfoBox);
应该也可以工作。
【讨论】:
以上是关于为啥即使 objectEquality 设置为 true,$watch 也不会触发?的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使在我将约束设置为 0 后 UITableView 上仍有余量
即使我将应用程序清单设置为纵向,为啥我的 Android 相机预览仍显示横向?
为啥即使我已将 withCredentials 设置为 true,Angular 也不通过 POST 请求发送 cookie?