Angular什么时候清除$ watch?

emc*_*emc 7 angularjs

我知道我在视图中包含的每个模型都会进入摘要循环并$watch应用于它,因为所有Angular应用程序基本上都是一个页面应用程序.但什么时候清楚了$watch

例如,假设我有view1.html包含模板的页面{{view.name1}}.当我切换路线的页面view2.html与模板{{view.name2}},莫非是$watch{{view.name1}} 自动未被注册或者我应该做手工?

Ila*_*mer 8

这个答案有角度范围源代码的链接,

每个范围都有一个私有数组$$watchers:

  • $watch调用该方法时,它会将侦听器推入$$watchers,请参阅Scope#$ watch.
  • 每次$digest迭代所有$$watchers,请参阅Scope#$ digest.
  • $destroy调用scope方法时,它会清除所有观察者,请参阅Scope#$ destroy
  • 每个范围也广播$destroy到它的所有子范围,无论是否隔离,所以你永远不会有孤儿范围.
  • Angular侦听DOM节点删除和$destroy所有指令范围(在$ compile服务中创建)的触发器,请参见此处

Angular会自动调用$destroy这些情况:


您只需$destroy在手动创建范围($new/ $transclude)时调用,并希望在父范围之前销毁它们.

ngView可能是一个很好的例子,因为你的应用程序中只有一个绑定到它的元素,并且该元素(通常是rootScope的范围)永远不会被销毁.因此,角度$new在进入路径时自动创建一个新的子范围(),并$destroy在存在时调用它,从而冲洗由该路径创建的所有观察者.

来自范围#$ new docs:

当需要将范围及其子范围与父级永久分离并因此通过调用停止参与模型更改检测和侦听器通知时,必须在范围上调用$ destroy().

来自$ compile - transclusion函数docs:

如果您打算在指令中手动添加和删除已转换的内容(通过调用transclude函数来获取DOM并调用element.remove()来删除它),那么您还要负责在转换范围上调用$ destroy.


以此为例,如果您手动创建了一个范围(带$new$transclude)并且不再需要它,但它的父范围是否需要手动销毁它.