ChatGPT解决这个技术问题 Extra ChatGPT

查看多个 $scope 属性

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

例如

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

P
Paolo Moretti

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

与 $watchCollection('[a, b]') 有什么区别?
不同之处在于您可以使用正确的数组而不是看起来像数组的字符串
我遇到了类似的问题,但使用了 controllerAs 模式。在我的情况下,修复包括在变量前面加上控制器的名称:$scope.$watchGroup(['mycustomctrl.foo', 'mycustomctrl.bar'],...
这在 Angular 1.6 上似乎对我不起作用。如果我在函数上添加控制台日志,我可以看到它只运行一次,newValuesoldValues 作为 undefined,同时单独观察属性正常工作。
R
Răzvan Flavius Panda

从 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 示例 here

文档here


请注意,第一个参数不是数组。这是一个看起来像数组的字符串。
谢谢你。如果它对我有用,我会给你一千金币——当然是虚拟金币:)
需要说明的是(我花了几分钟才意识到)$watchCollection 旨在传递一个对象并提供对任何对象属性更改的监视,而 $watchGroup 旨在传递一个单独的属性数组以注意更改。解决相似但不同的问题略有不同。呸!
不知何故,当您使用此方法时,newValues 和 oldValues 总是相等的:plnkr.co/edit/SwwdpQcNf78pQ80hhXMr
谢谢。它解决了我的问题。使用 $watch 是否有任何性能损失/问题?
A
Andrew Joslin

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

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

如果您的两个组合值很简单,则第一个参数通常只是一个角度表达式。例如,名字和姓氏:

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

这似乎是一个要求默认包含在框架中的用例。即使像 fullName = firstName + " " + lastName 这样简单的计算属性也需要传递一个函数作为第一个参数(而不是像 'firstName, lastName' 这样的简单表达式)。 Angular 是如此强大,但在某些领域,它可以以不(似乎)损害性能或设计原则的方式对开发人员更加友好。
好吧,$watch 只是接受一个角度表达式,它在它被调用的范围内进行评估。所以你可以做$scope.$watch('firstName + lastName', function() {...})。您也可以只做两个手表:function nameChanged() {}; $scope.$watch('firstName', nameChanged); $scope.$watch('lastName', nameChanged);。我在答案中添加了简单的案例。
'firstName + lastName' 中的加号是字符串连接。所以 Angular 现在只是检查连接的结果是否不同。
字符串连接需要一点小心——如果将“paran orman”更改为“para norman”,则不会触发响应;最好在第一个和第二个术语之间放置一个分隔符,如“\t|\t”,或者只使用确定的 JSON
虽然 amberjs 很烂,但它内置了这个功能!听到那些有棱角的家伙。我想做手表是最合理可行的方式。
K
Karen Zilles

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

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

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

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

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


我有一个类似的问题。这对我来说是正确的答案。
如果数组表达式中的项目不是简单类型,两者都会有轻微的性能开销。
这是真的.. 它正在对组件对象进行全面的深度比较。这可能是也可能不是你想要的。请参阅当前批准的使用现代角度的版本的答案,该版本不进行全深度比较。
出于某种原因,当我尝试在数组上使用 $watchCollection 时,我收到了这个错误 TypeError: Object #<Object> has no method '$watchCollection' 但这个解决方案可以帮助我解决我的问题!
很酷,您甚至可以查看对象中的值:$scope.$watch('[chaptercontent.Id, anchorid]', function (newValues, oldValues) { ... }, true);
Y
Yang Zhang

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

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

为什么使用 _this?在没有明确定义的情况下,范围不会被带到功能中吗?
我使用打字稿,呈现的代码是编译结果。
A
Adrian Mole

为什么不简单地将其包装在 forEach 中?

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

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


在这种情况下 log() 会被执行多次,对吧?我认为在嵌套 $watch 函数的情况下它不会。而且它不应该出现在同时查看多个属性的解决方案中。
不,每个监视属性的每次更改仅执行一次日志。为什么会被多次调用?
是的,我的意思是,如果我们想同时观看所有这些,那效果就不太好了。
确定为什么不呢?我在我的一个项目中就是这样做的。每当任一属性发生变化时都会调用 changed()。这与提供组合值的函数完全相同的行为。
稍有不同的是,如果数组中的多个项目同时更改, $watch 只会触发一次处理程序,而不是每个更改的项目一次。
J
Jay

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

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

或者

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

A
Artem Andreev

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


v
vinculis

怎么样:

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

如果没有 scope.$watch 的第三个 true 参数(如您的示例中所示),listener() 每次都会触发,因为匿名哈希每次都有不同的引用。
我发现这个解决方案适合我的情况。对我来说,它更像是:return { a: functionA(), b: functionB(), ... }。然后,我将新值和旧值的返回对象相互检查。
A
Akash Shinde
$scope.$watch('age + name', function () {
  //called when name or age changed
});

当年龄和名称值都更改时,将调用此处的函数。


还要确保在这种情况下不要使用 angular 传递给回调的 newValue 和 oldValue 参数,因为它们将是结果连接,而不仅仅是更改的字段
V
Vinit Solanki

Angular 在 1.3 版中引入了 $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]);
});