为什么赋值并不总是在Angular表达式中有效?

时间:2013-02-23 06:17:37

标签: javascript angularjs

我刚刚在Angular表达式允许的内容中发现了这种有趣的明显不一致性:

  1. 可以在表达式
  2. 中执行赋值
  3. 如果赋值涉及ngRepeat
  4. 中的局部变量,则会中断
  5. 这可以通过使用控制器中定义的setter而不是表达式
  6. 中的赋值来克服

    See Plunker

    docs on expressions似乎只是明确禁止表达式中的控制流,我没有看到上面提到的那种行为。

    我想从这里得到的结论是,无论如何使用setter可能是一个更好的设计模式,但有没有人知道关于表达式中可能的更明确的参考?

    如果Angular单方面禁止在其中进行转让,也许会更好。 (一个相关的不一致是,似乎可以在表达式中增加i = i + 1但不能用i + = 1 ......)

1 个答案:

答案 0 :(得分:11)

指令范围界定是一个已知问题。您可以阅读文章The Nuances of Scope Prototypal Inheritance以了解有关角度js中scoping的更多信息。

来自子/ transcluded范围的任何原始值赋值将创建新的实例值,而不是更改父范围值

在您的情况下,您使用的是原始值selectedNumber

有两种建议的解决方法

解决方案1 ​​
使用对象而不是原始值。

  1. 将selectedNumber更改为对象scope.selectedNumber = { num : 1 };
  2. 将显示更改为<h2>{{ selectedNumber.num }}</h2>
  3. ng-repeat中的点击处理程序更改为ng-click="selectedNumber.num = number"
  4. 演示:Plunker

    解决方案2:
    使用$parent范围参考

    1. ng-repeat中的点击处理程序更改为ng-click="$parent.selectedNumber = number"
    2. 演示:Plunker

      解决方案3:
      在父作用域中使用setter

      1. 在父作用域中创建一个setter方法,如$scope.setSelectedNumber = function(num){ $scope.selectedNumber = num}
      2. 将点击事件更改为setSelectedNumber(number) (这是已经使用过的方法)
      3. 更新:
        正如Anders Ekdahl所建议的那样,建议使用基于对象(解决方案1)的解决方案。