观察多个 $scope 属性

IT技术 javascript angularjs events angularjs-watch
2021-01-15 22:44:38

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

例如

$scope.$watch('item1, item2', function () { });
6个回答

从 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]') 有什么区别??
2021-03-15 22:44:38
不同之处在于您可以使用适当的数组而不是看起来像数组的字符串
2021-03-23 22:44:38
这在 Angular 1.6 上似乎对我不起作用。如果我将控制台日志放在该函数上,我可以看到它只使用newValuesoldValuesas运行一次undefined,同时单独观察属性像往常一样工作。
2021-03-23 22:44:38
我有一个类似的问题,但使用 controllerAs 模式。在我的情况下,修复包括在变量前面加上控制器的名称:$scope.$watchGroup(['mycustomctrl.foo', 'mycustomctrl.bar'],...
2021-04-06 22:44:38

从 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 示例在这里

文档在这里

要清楚(我花了几分钟才意识到)$watchCollection旨在传递一个对象并提供监视对象的任何属性的更改,而$watchGroup打算传递一组单个属性以监视更改。处理类似但不同的问题略有不同。呼!
2021-03-16 22:44:38
不知何故,使用此方法时,newValues 和 oldValues 始终相等:plnkr.co/edit/SwwdpQcNf78pQ80hhXMr
2021-03-16 22:44:38
谢谢。它解决了我的问题。使用 $watch 是否有任何性能影响/问题?
2021-03-19 22:44:38
请注意,第一个参数不是数组。它是一个看起来像数组的字符串。
2021-03-20 22:44:38
谢谢你。如果对我有用,我会给你一千金币——当然是虚拟的:)
2021-04-01 22:44:38

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

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

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

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

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

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

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

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

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

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

您可以使用 $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作用域在没有明确定义的情况下不会被传递到函数中吗?
2021-03-16 22:44:38
我使用typescript,呈现的代码是编译结果。
2021-03-22 22:44:38