如果范围变量不在对象中,为什么会赢得类工作?

时间:2014-11-23 11:36:02

标签: angularjs model scope

TL; DR跳到底部 - >

我在Codepen上发现了一个ng-class示例,here(下面重现了重要代码)。

在其中,作者创建了一个简单的菜单栏,突出显示活动项目。很标准。然而,我认为他这样做的方式很有趣,所以我把它修改为对我更有意义的东西,并且令人惊讶的是它破了。

作者创造了他的观点:

...
<div>Change the active menu item:
        <input ng-model="states.activeItem" />
</div>
<ul class="navigation">
        <li ng-repeat="item in items" class="item" ng-class="{'active': item.id == states.activeItem}" ng-click="states.activeItem=item.id">{{item.title}}</li>
</ul>
....

虽然他的控制器看起来像

app.controller('NavigationController', function ($scope) {
    // Must use a wrapper object, otherwise "activeItem" won't work
    $scope.states = {};
    $scope.states.activeItem = 'item1';
    $scope.items = [{
        id: 'item1',
        title: 'Home'
    }, {
        id: 'item2',
        title: 'Public Rooms'
    }, {
        id: 'item3',
        title: 'My Rooms'
    }];
});

对我来说,我认为跳过states变量并且只有一个

会更容易
$scope.activeItem

所以我将控制器更改为,并将视图更改为

<div>Change the active menu item:
        <input ng-model="states.activeItem" />
    </div>
    <ul class="navigation">
        <li ng-repeat="item in items" class="item" ng-class="{'active': item.id == activeItem}" ng-click="activeItem=item.id">{{item.title}}</li>
    </ul>

但它现在不起作用。

因此,出于某种原因,Angular需要将这些变量存储在新对象中。但为什么呢?


TL; DR:这两个都是Codepens:

The Original(效果很好)

Mine(不起作用)


为什么不开采工作?

1 个答案:

答案 0 :(得分:2)

这是因为ng-repeat指令在每次迭代中创建一个新范围。如 ng-repeat documentation

中所述
  

ngRepeat 指令从a中为每个项目实例化一次模板   采集。每个模板实例都有自己的范围,给定的范围   loop变量设置为当前集合项,并设置$ index   到项目索引或键。

使用对象通过范围继承为子范围提供对其父范围的访问。使用本机或基元,将选择当前子作用域仅访问父作用域一次,然后一旦为其分配了特定值,它将创建该本机/原始作用域变量。您可以将ng-click="activeItem=item.id"表达式作为先前陈述的证明。要解决此问题:您有两个选项,创建一个将状态保存到活动范围继承查找的对象,或使用$parent属性访问父范围ng-click="$parent.activeItem=item.id",这也适用于{ {1}}指令,ng-class

DEMO

<强> HTML

ng-class="{'active': item.id == $parent.activeItem}"