AngularJS:在ng-repeat中没有$ scope的变量处于其本地作用域中吗?

4
这里是代码:
<ul>
  <li ng-repeat="i in items" ng-class="{'red': click}">
    <span ng-click="click = !click">{{i}}</span>
  </li>
</ul>

<ul>
  <li ng-repeat="j in items" ng-class="{'red': f_click}">
    <span ng-click="fun_click($index)">{{j}}</span>
  </li>
</ul>

f_clickfun_click 函数中被更改。

$scope.fun_click = (idx) ->
    $scope.f_click = !$scope.f_click

完整的代码如下: http://plnkr.co/edit/Zmoqbv?p=preview 我想知道第一个列表中的变量“click”是每个ng-repeat元素的局部变量吗?它是如何工作的?
如何使第二个列表中的“f_click”像“click”一样工作? 看起来“$scope.f_click”是ng-controller中唯一的变量。
更新:
我想我做错了事。 我不应该在“View”中写东西。
在 View 中只读;在 Controller 中只写。 http://www.jacopretorius.net/2013/07/angularjs-best-practices.html

谢谢大家!我已经阅读了你们所有的回答,学到了很多!非常感谢你们!希望有一天我也能帮助到别人。 - zx1986
3个回答

4
我该如何让第二个列表中的f_click像click一样起作用呢?
据我所知,不可能。从你的第一个例子可以看出,click没有指定任何作用域。
而f_click指向特定的作用域,并且任何更改都会在所有元素(即循环中的所有项)上分配。
您可以根据每个值提供标志。
$scope.items2 = [
{'name': 'Google','value':false},
{'name': 'Apple','value':false},
{'name': 'Yahoo','value':false},
{'name': 'IBM','value':false},
];

 $scope.fun_click = (item) ->
   item.value = !item.value;

HTML

 <ul>
  <li ng-repeat="j in items2" ng-class="{'red': j.value}">
    <span ng-click="fun_click(j)">{{j.name}}</span>
  </li>
</ul>

请查看Plunker进行参考。


你甚至不需要给它们设置默认值为 false,你知道的:http://plnkr.co/edit/qgXbDp?p=preview - Ivan Chernykh
@Cherniv 你说得百分之百正确,但这样可以使代码更易读。两个月后,其他程序员需要花时间去理解为什么它是错误的。就像在Java中你可以写if(flag)或者if(flag==true)一样。 - Maxim Shoustin

3
ng-repeat为每次迭代创建一个作用域。变量click存在于每个ng-repeat作用域中,换句话说它是私有的。如果你将{{click}}放在<body ng-controller="MainCtrl">标签后但是ng-repeat标签前,它将不会显示任何内容,因为click只存在于内部作用域中。

相反,f_click存在于MainCtrl控制器作用域中,这是两个ng-repeat父级作用域。修改它的函数(fun_click)也存在于父级作用域中。ng-repeat作用域继承了单个实例的此变量,因此观察到了这种行为。

要使f_clickclick一样工作,您需要将其设置为每个ng-repeat迭代的作用域私有变量。一种解决方案是在ng-repeat内部定义一个控制器,然后在其中定义f_clickfun_click()。还有其他解决方案可供选择。


"ng-repeat为每个迭代创建一个作用域。" 谢谢!@Nikos 我会更深入地阅读文档。 - zx1986

3
第一个ngRepeat有效而第二个无效的原因是因为ngRepeat为每个项目创建了作用域。换句话说,对于items中的每个项目都有一个click变量的实例,并通过在ngClick中切换click变量来实际上使用私有实例。在第二个示例中,您使用控制器的$scope访问f_click,它是ngRepeat作用域的父级,因此更改会传播到所有子作用域。
因此,您问题的简单解决方法是将在ngRepeat中创建的f_click实例传递给函数。
// Script
$scope.fun_click = (toggle) ->
    return !toggle

// HTML
<span ng-click="f_click=fun_click(f_click)">{{j}}</span>

如果您希望在$scope中保持状态,可以使用字典来跟踪每个$index的状态:

// Script
$scope.form_status = {}
$scope.fun_click = (index) ->
    $scope.form_status[index] = !$scope.form_status[index]

// HTML
<li ng-repeat="j in items" ng-class="{'red': form_status[$index]}">
    <span ng-click="fun_click($index)">{{j}}</span>
</li>

这是更新的 Plunker 链接:http://plnkr.co/edit/w6RLed?p=preview

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接