Angular 2变化检测 - 组件之间的循环依赖如何解决?

Fju*_*jut 3 angular2-changedetection angular

我已经读过Angular 2变化检测是单向的,从组件树的顶部到底部,并且在单次传递后它变得稳定,这意味着没有多个变化检测周期.鉴于这些假设,在我们有父和子组件具有相互依赖属性的情况下会发生什么?例:

  1. 基于用户事件,父组件更新子组件属性
  2. 此更新将触发子组件中更新父项属性的事件
  3. 父属性更新将触发另一个更新子组件的事件
  4. ...

根据我的理解,Angular 1中的类似情况通过设置对这些相互依赖的属性触发的循环次数的限制来解决,这将导致框架抛出错误.

Angular 2如何解决?在上面的例子中,在哪一点上实际触发了变化检测?

Mar*_*cok 7

我已经读过Angular 2变化检测......一次通过后变得稳定

Angular 2没有"稳定".使用Angular 2应用程序,我们负责编写应用程序,使其在单次传递后始终保持稳定.

默认情况下(例如,您没有OnPush在任何组件上使用更改检测策略,也没有分离()任何组件),更改检测的工作方式如下:

  • Zone.js猴子修补的异步事件触发 - 例如,(click)事件,XHR响应,setTimeout()计时器.与该事件关联的回调运行,这可以更改我们的应用程序中的任何视图或应用程序数据.然后,由于猴子补丁,角度变化检测运行.换句话说,默认情况下(例如,您不是手动触发更改检测),只有猴子修补的异步事件会触发更改检测.
  • 从根组件开始,遍历组件树(深度优先遍历),检查每个数据绑定的变化.如果发现更改,则"传播"更改.根据模板绑定类型,传播可以
    • 将更改的值传播到DOM.例如,当使用{{}}绑定时,新值将传播到textContent适当DOM元素的属性.
    • 将更改的值传播到子组件.例如,当使用输入属性binding([childInputProperty]="parentProperty")时,新值将传播到子输入属性.
  • 如果处于开发模式,则会再次检查所有组件,但不会传播.这第二次脏检查有助于我们发现代码存在问题,例如,如果我们违反了幂等规则,这是一种奇特的说法,即我们的一个绑定(其模板表达式)具有副作用.换句话说,额外的开发模式检查让我们知道我们的代码在单次传递后是否不稳定.

Angular 2中不允许出现副作用.在引用您的问题时,子组件因此不能因输入属性传播而修改父属性.所以,你可以说Angular 2通过不允许它来解决你所问的情况.

这并不像听起来那么糟糕.我知道输入属性传播可以更改父属性的唯一方法是,子组件为input属性实现setter方法,该方法修改父对象在其模板中显示的另一个属性.(这是一个做这个的旧手 - 看看@Input set backdoor()方法.)通常你不会这样做.如果你确实需要这样做,那么Günter的评论就在于:在a里面进行更改setTimeout(),因此它将成为下一个更改检测周期的一部分.

我想再强调一下:事件处理程序在更改检测之前运行,因此他们可以自由地更改我们应用程序中的任何数据 - 本地/组件视图数据,应用程序数据等等.因此,在事件处理程序中,子组件可以自由更改父数据.例如,假设父和子都具有对同一数组的引用.当事件处理程序运行时,父组件和/或子组件可以修改该数组.

因此,如果您在事件处理程序中进行更改,则没有问题.如果你的二传手做了奇怪的事,那就只有一个问题.

  • 你可以使用`setTimeout(changeParentHere)`如果这真的是你想要的. (2认同)