AngularJS工厂属性为';当不使用push()时,$scope中的t正在更新

AngularJS工厂属性为';当不使用push()时,$scope中的t正在更新,angularjs,angularjs-scope,angularjs-service,Angularjs,Angularjs Scope,Angularjs Service,我有一个工厂正在从外部源检索数据。一旦我得到数据,我就使用第二个工厂按照特定标准对其进行过滤 factory属性已指定给范围 现在,当我在工厂中执行此操作时,它不会更新范围: factory.foo = [{id:1,name:'foo'}]; // doesn't work 因此,第二家工厂的过滤器也不能工作 factory.foo = Filter.filter(); // doesn't work 虽然这样做有效: factory.foo.push({id:1,name:'foo'})

我有一个工厂正在从外部源检索数据。一旦我得到数据,我就使用第二个工厂按照特定标准对其进行过滤

factory属性已指定给范围

现在,当我在工厂中执行此操作时,它不会更新范围:

factory.foo = [{id:1,name:'foo'}]; // doesn't work
因此,第二家工厂的过滤器也不能工作

factory.foo = Filter.filter(); // doesn't work
虽然这样做有效:

factory.foo.push({id:1,name:'foo'}); // works
是否有人知道这是有意的,为什么会这样,以及如何解决


问题是您的工厂替换了对
factory.foo的引用。初始化作用域时,
$scope.foo
保存对数组的引用(空)。当您调用
Foo.getDataForFoo
时,它会在内部将引用更改为
Factory.Foo
,但您的作用域仍保留对上一个数组的引用。这就是为什么使用
push
会起作用,因为它不会更改数组引用,而是更改数组内容

有几种方法可以解决这个问题。在不使用所有不同选项的情况下,最简单的方法是将
$scope.foo
包装到函数中,返回
Factory.foo
。这样,Angular将检测摘要循环中的引用更改,并相应地更新视图

app.controller('MainCtrl', function($scope,Foo) {
  $scope.test = 'running';
  $scope.foo = function() { return Foo.foo };

  $scope.click = Foo.getDataForFoo
});

// And in the view (the relevant part)

<ul ng-repeat="elem in foo()">
  <li>{{elem.id}} {{elem.name}}</li>
</ul>
<a href="" ng-click="click()">add</a>
app.controller('MainCtrl',函数($scope,Foo){
$scope.test='running';
$scope.foo=function(){return foo.foo};
$scope.click=Foo.getDataForFoo
});
//以及在视图中(相关部分)
  • {{elem.id}{{elem.name}

@Simon Belanger的答案是正确的,他提出了一个可行的解决方案


另一种选择是清空数组并将新项目推入其中(例如,对于刷新事件),而不是通过为其分配新数组来重置引用。您可以通过指定长度来截断数组:
myArray.length=0
,然后您可以通过
array迭代新集合以填充新条目。push()

Simon Belanger说,您失去了引用。我在这里解释:关于作用域继承的完整解释,请看这个答案@piatek,我不认为它与作用域继承有关,因为我这里只有一个作用域。请原谅,我已经跳过了枪,因为我之前遇到过类似的问题,但与作用域有关!谢谢你的解释。这是一个好方法…还是有更好/更干净的实践方法?当您期望外部事物的引用更改时,这是一个好方法。正如您所发现的,一个选项是直接更改数组的内容(推送、拼接等),或者您可以将函数逻辑移动到工厂(即
Foo.Foo
是返回数组的函数),但您仍然必须在模板中使用
Foo()
。另一个选项是在调用
getDataForFoo
之后重新获取
Foo.Foo
,比如:
$scope.click=function(){Foo.getDataForFoo();$scope.Foo=Foo.Foo;}。在这一点上,您是否喜欢使用计算属性(函数)实际上是一个偏好问题this@user2422960我之前的评论简要解释了当时我可以想到的其他选择
app.controller('MainCtrl', function($scope,Foo) {
  $scope.test = 'running';
  $scope.foo = function() { return Foo.foo };

  $scope.click = Foo.getDataForFoo
});

// And in the view (the relevant part)

<ul ng-repeat="elem in foo()">
  <li>{{elem.id}} {{elem.name}}</li>
</ul>
<a href="" ng-click="click()">add</a>