76

将 AngularJS 与其他 JavaScript-MVC 框架区分开来的一件事是它能够使用绑定将 JavaScript 中的绑定值回显到 HTML 中。当您为 $scope 变量分配任何值时,Angular 会“自动”执行此操作。

但这有多自动化?有时,Angular 不会接受更改,所以我需要调用 $scope.$apply() 或 $scope.$digest() 来通知 Angular 接受更改。有时,当我运行其中任何一种方法时,它都会引发错误并说摘要已经在进行中。

由于绑定({{}} 大括号或 ng 属性中的任何内容)都与 eval 相呼应,这是否意味着 Angular 会不断轮询 $scope 对象以查找更改,然后执行 eval 以将这些更改推送到 DOM/ HTML?或者 AngularJS 是否以某种方式找出了使用魔法变量,这些变量会在变量值更改或分配时触发事件?我从未听说过所有浏览器都完全支持它,所以我对此表示怀疑。

AngularJS 如何跟踪它的绑定和作用域变量?

4

2 回答 2

64

除了 Mark 发现的文档部分,我认为我们可以尝试列举所有可能的变化来源。

  1. 用户与 HTML 输入('text''number''url''email''radio''checkbox')的交互。AngularJS 有inputDirective。'text'、'number'、'url' 和 'email' 输入为 'input' 或 'keydown' 事件绑定侦听器处理程序。侦听器处理程序调用 scope.$apply。'radio' 和 'checkbox' 为单击事件绑定类似的处理程序。
  2. 用户与选择元素的交互。AngularJS 的selectDirective在 'change' 事件上有类似的行为。
  3. 使用同样执行$rootScope.$apply()的$timeout 服务进行定期更改。
  4. eventDirectives(ngClick 等)也使用scope.$apply
  5. $http 也使用$rootScope.$apply()
  6. 如您所知,AngularJS 世界之外的更改应该使用 scope.$apply。
于 2012-09-19T08:52:58.257 回答
5

正如您发现它不是轮询,而是使用它的内部执行循环,这就是为什么您需要使用 $apply() 或 $digest() 来启动事情。

Miško 的解释非常透彻,但缺少一点是 Angular 只是试图让 $scope 在它自己的上下文中发生任何事情时回到一个清晰的内部状态。这可能需要在模型状态之间进行相当多的反弹,所以这也是为什么你不能依赖 $watch() 只触发一次的原因,也是为什么你应该小心手动设置模型之间的关系,否则你会无休止地结束循环刷新。

于 2012-09-19T00:23:49.000 回答