Angular:变量存储在哪里'如果他们在ng-init中设置?

时间:2015-10-01 09:10:21

标签: angularjs angularjs-scope angularjs-ng-repeat

这个ng-init变量究竟在哪里' someData'存储

<tr data-ng-repeat="item in items" ng-init="someData=1">
 <td>{{item.id}}</td>
 <td>{{someData}}</td>
</tr>

如何从外部访问它,即从应该设置someData = someData + 1的函数中访问它?

1 个答案:

答案 0 :(得分:0)

视图中定义的变量在当前范围上定义。但是,要知道当前范围实际上并不总是那么容易。您当前的范围由创建范围的最近元素决定。

简单案例

如果您直接位于控制器内部,那么您当前的范围是该控制器的$ scope变量。如下例所示:

在您的HTML中
<div ng-controller="MyController">
    <div ng-init="someData = 1">
    </div>
</div>
在MyController中
$timeout(function() {
    console.log($scope.someData); // Logs 1
})

变量“someData”是在MyController的范围内定义的。注意超时,这是必需的,因为控制器在解析视图之前运行,所以如果我们立即记录,ng-init将不会运行且变量未定义。

如果您要嵌套两个控制器,然后在其中执行ng-init,它将分配给最近的控制器。因此,如果您有控制器A并且内部有控制器B,并且您在内部执行ng-init,那么它将在控制器B内分配变量,而不是A.

不太简单的案例

如果您使用您的代码尝试上述解决方案,它将无法正常工作。原因是你正在使用转发器。一个ng-repeat,以及大多数其他指令将创建自己的范围!在您的情况下,someData将在转发器的内部范围上定义,您的控制器无法访问!这是btw,其中来自repeat的“item”变量存储在该行的本地转发器范围中。转发器中的每一行都有自己的新范围,这就是为什么你在每一行使用相同的“item”变量,但每次都意味着不同的事情。

<div ng-controller="MyController">
    We are now in the scope of MyController.
    Variables defined here can be find in $scope of MyController.

    <div ng-repeat="foo in bar">
        We are now in the local repeater scope, one for each row.
        Note that the containing div is part of the scope.
        Variables defined here go on the local scope, MyController can't find them.
    </div>

    The repeater scope has ended, we are back in MyController

    <div ng-include="someview.html">
       And now we are in the local scope of the ng-include!
       This scope works just like the ng-repeat one does.
    </div>
</div>

这与javascript中的继承如何工作有关。请注意,如果你获取一个仅存在于父项中的变量(比如将其打印出来),那么它可以正常工作。在javascript中,当你得到一个变量时,它会逐步增加继承链,直到找到它为止。 Vut一旦你试图一个值分配给某个东西,它就会创建它自己的局部变量,然后从那里开始使用它。

因此,在您的情况下,您实际上无法从控制器中找到它(除非您将其作为参数发送到函数中),因为父作用域无法访问子作用域。

更好的方式

有几种方法可以解决这个问题。建议的方法是使用控制器作为语法。它在documentation for ng-controller中描述,但简而言之,您将变量直接分配给控制器对象(而不是$ scope对象),然后在视图中调用控制器时给控制器命名。这使您可以明确指出您所使用的控制器中的哪个变量。

在MyController中
this.data = {};
在您的HTML中
<div ng-controller="MyController as MC">
    <div ng-controller="item in items" ng-init="MC.someData = 1">
    </div>
</div>

由于您现在在“MC”控制器上显式创建someData,因此不再存在混淆。无论有多少指令或控制器嵌套在内,你都确切知道数据的最终位置。注意“item”仍在转发器范围内,但这是好的,因为它应该是转发器的内部。如果您需要,可以使用函数将其传递出去,或理论上将其传递给转发器内的ng-init。