angular2 如何决定是更新还是重新创建组件?

Posted

技术标签:

【中文标题】angular2 如何决定是更新还是重新创建组件?【英文标题】:How does angular2 decide whether to update or recreate a component? 【发布时间】:2016-03-18 15:00:24 【问题描述】:

假设我有一个 Angular2 组件,它有一些输入属性,比如

@Component(...)
class ChildComponent 
   @Input() input1: string;
   @Input() input2: number;
   internalState: any;

在另一个组件中使用,甚至可能在列表中,例如:

<li *ngFor="#item of items">
  <child-component [input1]="item.a" [input2]="item.b">
  </child-component>
</li>

输入参数发生变异的地方:

Angular2 如何决定是否应该更新子组件(将输入变量设置为新值并调用ngOnChanges 生命周期挂钩)或者是否应该销毁它并创建一个新组件?有没有可能影响行为?

我问的原因是因为如果组件除了输入参数之外还有任何内部状态,那么更新或重新创建它会有所不同。在更新的情况下,它将保持旧的内部状态(例如,如果某些东西被折叠,如果用户输入了一些东西),在重新创建的情况下,我们将获得一个具有默认状态的新初始化组件。

根据组件,我肯定有时需要第一种方法,有时需要另一种方法。

如果组件有一些复杂的初始化逻辑并且不存储用户数据,那么我认为将输入视为不可变并且只在 ngOnInit 中初始化组件一次而不是考虑需要在 ngOnChanges 上做什么会更容易.

当存在像给定示例中的子组件列表时,问题变得更加棘手。如果为我提供列表的服务现在在列表中间插入一个新项目并给我一个更新的列表(可能是不可变列表的突变或新版本) - angular2 如何知道我想要一个新的要在列表中间创建项目,而不是用新值更新现有项目并在最后创建一个新项目?后一种方法会将先前现有项目的内部状态转移到新项目,并且先前现有项目的输入数据将被分配给新创建的组件。

【问题讨论】:

【参考方案1】:

引用NgFor docs:

Angular 使用对象标识来跟踪迭代器中的插入和删除,并在 DOM 中重现这些更改。这对存在的动画和任何有状态的控件(例如接受用户输入的&lt;input&gt; 元素)具有重要意义。插入的行可以动画化,删除的行可以动画化,未更改的行保留任何未保存的状态,例如用户输入。

您可能想阅读文档中的一些其他详细信息。

【讨论】:

谢谢,我查看了开发人员指南章节,但没有查看 NgFor 的 API 文档,因此没有找到。看起来合理且易于理解(只需为每个章节使用可变对象的单个实例容器中的项目)。虽然有趣的是,如果只使用不可变的数据结构(就像它目前在 React 生态系统中流行的那样),它就会崩溃。您对围绕它的自定义选项有什么想法吗? NgFor 文档提到了一个迄今为止未记录的 IterableDiffers 参数,这听起来有帮助吗? @Matthias247,对不起,没有想法。最近才开始学习A2,尽量避免看A2源码。

以上是关于angular2 如何决定是更新还是重新创建组件?的主要内容,如果未能解决你的问题,请参考以下文章

Angular2,如何只重新加载一次组件?

react中key值的理解

如何在 Angular 2 中强制组件重新渲染?

如何在多个 Angular 2 项目之间共享一个 Angular 2 组件?

Angular2 NgFor在表达式中绑定数组

Angular 2 路由器:添加 RouteParam 而不重新创建组件