Angular:即使objectEquality = true,也不会触发范围监视

时间:2013-05-23 20:32:46

标签: javascript angularjs

在我的控制器中我有:

$scope.$watch('numRuns', function(newVal, oldVal) {
  if (newVal === oldVal) return;
  updateNumResults();
});

function updateNumResults() {
  $scope.resultSet.size($scope.numRuns);
  console.log("updateNumResults called");
}

ResultSet中的size方法如下所示:

  function size(n) {
    if (n === undefined) return numResults_; // no arg => using as getter
    numResults_ = n;
    return this;
  }

在我看来,我有:

Number of runs: <input ng-model="numRuns"/>

在我的指示中,我有:

scope.$watch('resultSet', function(newVal, oldVal) {
  console.log("change in result set");
  createFromScratch();
}, true); // use object equality

如果我在浏览器中键入输入框,我会看到输出“updateNumResults”,但不会调用'resultSet'上的实际监视。我已经验证对象“resultSet”确实因调用size()而变异,并且由于我已将objectEquality参数设置为“true”而设置了监视,我的理解是应该选择更改起来并触发手表。为什么不发生这种情况,我该如何实现呢?

更新

我进行了以下更改以使其正常工作:

创建了一个简单的计数器变量,我每次在resultSet上调用任何mutator方法时都会手动更改:

  function updateNumResults() {
    $scope.resultSet.size($scope.numRuns);
    $scope.resultSetChanged++; 
    console.log("updateNumResults called");
  }

我在指令中看到了这一点:

  function watchResultSet() {
    scope.$watch('resultSetChanged', function(newVal, oldVal) {
      console.log("change in result set");
      createFromScratch();
    });
  }

此解决方案工作正常,可能资源消耗较少,但我仍然想知道原始解决方案无法正常工作的原因。

更新2与JSBIN示例

Sh0ber的想法是正确的。问题出在私人诉讼中。

  1. JSbin using private vars (revealing module pattern) showing the problem
  2. JSbin using normal objects works

2 个答案:

答案 0 :(得分:2)

这个答案是基于问题中的一些讨论:

如果resultSet对象发生变异,则此代码工作。在查看size方法之后,它似乎只是在resultSet的构造函数中改变了一些私有变量。 <{1}}对象本身没有改变,因此永远不会触发resultSet

答案 1 :(得分:0)

我的猜测是,您已将指令配置为具有单独的隔离范围(您已将散列传递给scope参数)。由于您已在指令范围内配置了监视,因此需要确保此范围与控制器范围相同,或者继承它。

阅读Angular guide on directives(特别是关于范围配置)以获取更多信息。