观看多个$scope属性

Watch multiple $scope attributes

提问人:Greg 提问时间:8/14/2012 最后编辑:Mosh FeuGreg 更新时间:7/7/2022 访问量:195179

问:

有没有办法使用$watch

例如

$scope.$watch('item1, item2', function () { });
JavaScript 事件 angularjs-watch

评论


答:

118赞 Andrew Joslin 8/14/2012 #1

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

$scope.$watch(function watchBothItems() {
  return itemsCombinedValue();
}, function whenItemsChange() {
  //stuff
});

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

$scope.$watch('firstName + lastName', function() {
  //stuff
});

评论

8赞 XML 8/25/2012
这似乎是一个默认要求包含在框架中的用例。即使是像这样简单的计算属性也需要将函数作为第一个参数传递(而不是像 这样的简单表达式)。Angular 非常强大,但在某些领域,它可以在不(似乎)损害性能或设计原则的方式对开发人员更加友好。fullName = firstName + " " + lastName'firstName, lastName'
4赞 Andrew Joslin 8/25/2012
好吧$watch只采用一个角度表达式,该表达式在调用的示波器上进行评估。所以你可以做.您也可以只做两块手表:.我在答案中添加了简单的案例。$scope.$watch('firstName + lastName', function() {...})function nameChanged() {}; $scope.$watch('firstName', nameChanged); $scope.$watch('lastName', nameChanged);
0赞 mb21 9/6/2012
“firstName + lastName”中的加号是字符串连接。所以 angular 现在只是检查串联的结果是否不同。
16赞 Dave Edelhart 10/8/2012
字符串连接需要一点小心 - 如果您将“paran orman”更改为“para norman”,则不会触发响应;最好在第一项和第二项之间放置一个像“\t|\t”这样的分隔符,或者只是坚持使用确定的 JSON
0赞 Aladdin Mhemed 10/24/2012
虽然 Amberjs 很烂,但它内置了这个功能!听听那些棱角分明的家伙。我想做手表是最合理可行的方式。
5赞 Artem Andreev 8/14/2012 #2

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

11赞 guyk 10/2/2012 #3

合并值的一个稍微安全的解决方案可能是使用以下函数:$watch

function() { return angular.toJson([item1, item2]) }

$scope.$watch(
  function() {
    return angular.toJson([item1, item2]);
  },
  function() {
    // Stuff to do after either value changes
  });
4赞 wacamo 11/13/2012 #4

怎么样:

scope.$watch(function() { 
   return { 
      a: thing-one, 
      b: thing-two, 
      c: red-fish, 
      d: blue-fish 
   }; 
}, listener...);

评论

2赞 Peter V. Mørch 1/27/2014
如果没有第三个参数 to(如您的示例所示),则每次都会触发,因为匿名哈希每次都有不同的引用。truescope.$watchlistener()
0赞 RevNoah 3/18/2014
我发现这个解决方案适合我的情况。对我来说,它更像是:.然后,我检查新值和旧值的返回对象。return { a: functionA(), b: functionB(), ... }
72赞 Karen Zilles 1/19/2013 #5

这是一个与实际有效的原始伪代码非常相似的解决方案:

$scope.$watch('[item1, item2] | json', function () { });

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

$scope.$watch('[item1, item2]', function () { }, true);

基本上我们跳过了 json 步骤,这一开始看起来很愚蠢,但如果没有它,它就无法工作。它们的关键是经常被省略的第三个参数,它打开了对象相等性,而不是引用相等性。然后,我们创建的数组对象之间的比较实际上是正确的。

评论

0赞 Calvin Cheng 5/31/2013
我有一个类似的问题。这对我来说是正确的答案。
0赞 null 8/18/2013
如果数组表达式中的项不是简单类型,则两者都有轻微的性能开销。
0赞 Karen Zilles 8/27/2013
这是真的..它正在对组件对象进行全面的深度比较。这可能是也可能不是你想要的。请参阅当前批准的答案,了解使用现代 angular 的版本,该版本未进行完整的深度比较。
0赞 abottoni 9/10/2013
出于某种原因,当我尝试在数组上使用$watchCollection时,我遇到了此错误,但此解决方案帮助我解决了我的问题!TypeError: Object #<Object> has no method '$watchCollection'
0赞 Serge van den Oever 1/28/2014
很酷,您甚至可以观察对象中的值:$scope.$watch('[chaptercontent.Id, anchorid]', function (newValues, oldValues) { ... }, true);
12赞 user187676 5/12/2013 #6

为什么不简单地把它包裹在一个?forEach

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

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

评论

0赞 John Doe 5/13/2013
在这种情况下,log() 会被执行几次,对吧?我认为在嵌套$watch函数的情况下,它不会。它不应该在同时观看多个属性的解决方案中。
0赞 5/13/2013
否,日志仅对每个监视属性的每次更改执行一次。为什么会多次调用它?
0赞 John Doe 5/13/2013
是的,我的意思是,如果我们想同时观看所有这些视频,那就不好用了。
1赞 5/13/2013
当然为什么不呢?我在我的一个项目中就是这样做的。 每当任一属性发生更改时,都会调用。这与为组合值提供函数的行为完全相同。changed()
1赞 bingles 10/30/2014
它略有不同,因为如果数组中的多个项目同时更改,则$watch将仅触发处理程序一次,而不是每个更改的项目触发一次。
292赞 Răzvan Flavius Panda 6/21/2013 #7

从 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
});

Plunker 示例在这里

文档在这里

评论

109赞 M.K. Safi 9/23/2013
请注意,第一个参数不是数组。它是一个看起来像数组的字符串。
1赞 AdityaSaxena 8/20/2014
谢谢你。如果它对我有用,我会给你一千个金币——当然是虚拟的:)
5赞 Mattygabe 2/28/2015
需要明确的是(我花了几分钟才意识到)旨在传递一个对象并提供对对象任何属性更改的监视,而旨在传递单个属性的数组以监视其更改。略有不同,以解决相似但不同的问题。唷!$watchCollection$watchGroup
1赞 mostruash 5/4/2016
不知何故,当您使用此方法时,newValues 和 oldValues 始终相等: plnkr.co/edit/SwwdpQcNf78pQ80hhXMr
0赞 Syed Nasir Abbas 7/3/2017
谢谢。它解决了我的问题。使用$watch是否存在任何性能影响/问题?
602赞 Paolo Moretti 5/6/2014 #8

从 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 
});

评论

7赞 Kamil Tomšík 1/12/2015
与 $watchCollection('[a, b]') 有什么区别??
30赞 Paolo Moretti 2/25/2015
不同之处在于,您可以使用适当的数组,而不是看起来像数组的字符串
2赞 morels 10/15/2015
我遇到了类似的问题,但使用 controllerAs 模式。就我而言,修复包括在变量前面附加控制器的名称:$scope.$watchGroup(['mycustomctrl.foo', 'mycustomctrl.bar'],...
1赞 Alejandro García Iglesias 4/4/2017
这似乎在 Angular 1.6 上对我不起作用。如果我在函数上放置控制台日志,我可以看到它只运行一次 和 as ,同时单独观察属性照常工作。newValuesoldValuesundefined
4赞 Akash Shinde 4/17/2015 #9
$scope.$watch('age + name', function () {
  //called when name or age changed
});

当年龄和名称值都更改时,这里函数将被调用。

评论

2赞 Akash Shinde 4/17/2015
此外,请确保在这种情况下不要使用 angular 传递到回调中的 newValue 和 oldValue 参数,因为它们将是生成的串联,而不仅仅是已更改的字段
15赞 Yang Zhang 5/21/2015 #10

可以使用 $watchGroup 中的函数来选择作用域中对象的字段。

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

评论

1赞 sg.cc 5/22/2015
你为什么使用?作用域不是在没有明确定义的情况下被转移到函数中吗?_this
1赞 Yang Zhang 5/22/2015
我使用打字稿,呈现的代码是编译结果。
1赞 Vinit Solanki 4/2/2018 #11

在 1.3 版中引入的 Angular 可以使用它来观察多个变量,单个块将数组作为第一个参数,我们可以在其中包含所有要观察的变量。$watchGroup$watchGroup$watchGroup

$scope.$watchGroup(['var1','var2'],function(newVals,oldVals){
   console.log("new value of var1 = " newVals[0]);
   console.log("new value of var2 = " newVals[1]);
   console.log("old value of var1 = " oldVals[0]);
   console.log("old value of var2 = " oldVals[1]);
});