观察多个$ scope属性

Gre*_*reg 438 javascript events angularjs angularjs-watch

有没有办法使用多个对象订阅事件 $watch

例如

$scope.$watch('item1, item2', function () { });
Run Code Online (Sandbox Code Playgroud)

Pao*_*tti 582

从AngularJS 1.3开始,有一个新方法,$watchGroup用于观察一组表达式.

$scope.foo = 'foo';
$scope.bar = 'bar';

$scope.$watchGroup(['foo', 'bar'], function(newValues, oldValues, scope) {
  // newValues array contains the current values of the watch expressions
  // with the indexes matching those of the watchExpression array
  // i.e.
  // newValues[0] -> $scope.foo 
  // and 
  // newValues[1] -> $scope.bar 
});
Run Code Online (Sandbox Code Playgroud)

  • 不同之处在于您可以使用正确的数组而不是看起来像数组的字符串 (28认同)
  • 与$ watchCollection('[a,b]')的区别是什么? (7认同)
  • 我有一个类似的问题,但使用controllerAs模式.在我的例子中,修复包括在变量前面加上控制器的名称:`$ scope.$ watchGroup(['mycustomctrl.foo','mycustomctrl.bar'],...` (2认同)

Răz*_*nda 290

从AngularJS 1.1.4开始,您可以使用$watchCollection:

$scope.$watchCollection('[item1, item2]', function(newValues, oldValues){
    // do stuff here
    // newValues and oldValues contain the new and respectively old value
    // of the observed collection array
});
Run Code Online (Sandbox Code Playgroud)

这里有 Plunker的例子

文档在这里

  • 请注意,第一个参数是**而不是**数组.它是一个看起来像数组的字符串. (109认同)
  • 要清楚(花了我几分钟才意识到)`$ watchCollection`旨在交给一个对象并提供一个监视任何对象属性的更改,而`$ watchGroup`旨在交给一个人的数组要监视更改的属性.解决类似但不同的问题略有不同.唷! (5认同)

And*_*lin 118

$watch 第一个参数也可以是一个函数.

$scope.$watch(function watchBothItems() {
  return itemsCombinedValue();
}, function whenItemsChange() {
  //stuff
});
Run Code Online (Sandbox Code Playgroud)

如果您的两个组合值很简单,则第一个参数通常只是一个角度表达式.例如,firstName和lastName:

$scope.$watch('firstName + lastName', function() {
  //stuff
});
Run Code Online (Sandbox Code Playgroud)

  • 字符串连接需要一点小心 - 如果你将"paran orman"改为"para norman"而不是你不会触发响应; 最好在第一个和第二个术语之间放置一个像"\ t |\t"这样的分隔符,或者只是坚持使用最终的JSON (16认同)
  • 这似乎是一个默认情况下迫切要求包含在框架中的用例.即使像`fullName = firstName +""+ lastName`这样简单的计算属性也需要将函数作为第一个参数传递(而不是像`'firstName,lastName'`这样的简单表达式).Angular非常强大,但在某些方面,它可以以不会(似乎)影响性能或设计原则的方式对开发人员更加友好. (8认同)
  • 那么$ watch只需要一个角度表达式,它在被调用的范围内进行评估.所以你可以做`$ scope.$ watch('firstName + lastName',function(){...})`.你也可以做两个手表:`function nameChanged(){}; $ scope.$ watch('firstName',nameChanged); $ scope.$ watch('lastName',nameChanged);`.我在答案中添加了简单的案例. (4认同)

Kar*_*les 70

这是一个非常类似于原始伪代码的解决方案,它实际上有效:

$scope.$watch('[item1, item2] | json', function () { });
Run Code Online (Sandbox Code Playgroud)

编辑:好的,我认为这更好:

$scope.$watch('[item1, item2]', function () { }, true);
Run Code Online (Sandbox Code Playgroud)

基本上我们正在跳过json步骤,这一步似乎开始时是愚蠢的,但没有它就无法工作.它们的关键是经常省略的第3个参数,它打开对象相等而不是引用相等.然后我们创建的数组对象之间的比较实际上是正确的.


Yan*_*ang 15

您可以使用$ watchGroup中的函数来选择范围内对象的字段.

        $scope.$watchGroup(
        [function () { return _this.$scope.ViewModel.Monitor1Scale; },   
         function () { return _this.$scope.ViewModel.Monitor2Scale; }],  
         function (newVal, oldVal, scope) 
         {
             if (newVal != oldVal) {
                 _this.updateMonitorScales();
             }
         });
Run Code Online (Sandbox Code Playgroud)


Eri*_*ner 12

为什么不简单地把它包装成forEach

angular.forEach(['a', 'b', 'c'], function (key) {
  scope.$watch(key, function (v) {
    changed();
  });
});
Run Code Online (Sandbox Code Playgroud)

它与为组合值提供函数的开销大致相同,而实际上不必担心值组合.


小智 11

组合值的更安全的解决方案可能是使用以下$watch功能:

function() { return angular.toJson([item1, item2]) }
Run Code Online (Sandbox Code Playgroud)

要么

$scope.$watch(
  function() {
    return angular.toJson([item1, item2]);
  },
  function() {
    // Stuff to do after either value changes
  });
Run Code Online (Sandbox Code Playgroud)


Art*_*eev 5

$ watch第一个参数可以是角度表达式或函数.请参阅$ scope的文档.$ watch.它包含许多关于$ watch方法如何工作的有用信息:调用watchExpression时,角度如何比较结果等.