Angular执行渲染和更新视图的方式是理解框架内部系统和基本功能的关键因素。让我们暂停几分钟,以更好地了解Angular的变更检测策略的工作方式。

什么是“变更检测策略(Change Detection)” ?

首先我们需要了解什么是变更检测策略?

变更检测的基本机制是针对两种状态执行检查,一种是当前状态,另一种是新状态。如果一个状态与另一个状态不同,则说明已经变更,这意味着我们需要更新(或重新渲染)视图。

变更检测意味着在数据变更后更新视图(DOM)。

变更检测分两步完成

Angular的变更检测分为两个步骤,第一个步骤是通过开发人员更新应用程序的模型来完成。他可以通过更改组件的属性或触发事件来做到这一点。然后,Angular的工作将是通过重新渲染来在视图中呈现模型的状态。通常,这意味着Angular将通过触发事件或着通过属性绑定来进行更新。

  1. 更新应用程序的模型(开发者)
  2. 在视图中呈现模型状态(Angular)

流程

为了能够正确演示Angular的变更检测流程,我们需要举一个例子。在Angular中,每个应用程序都是将一堆组件与一些输入和输出组合在一起,以便能够传播数据和模型状态。应用程序基本上由我们所谓的组件树组成。
组件树
如果我们使用上图所示的待办事项应用程序,那我们将有一个相当简单的应用程序,它具有一个TodosComponent来管理TodoComponent的列表。如果我们修改这个列表,则通过更改待办事项列表第一项的值(以黄色显示),我们将获得以下流程:

  1. 开发者正在修改模型(例如组件的绑定属性);
  2. Angular的变更检测开始传播变更;
  3. 变更检测遍历组件树中的每个组件(从上到下),以检查它所依赖的模型是否已变更;
  4. 如果已模型已变更,将会更新组件;
  5. Angular更新组件视图(DOM)。

Angular通过从顶部开始一直持续到到达底部来进行变更检测的方式,使系统更具可预测性和性能。

Angular变更检测策略

Angular提供了两种变更检测策略,默认策略和OnPush策略。

ChangeDetectionStrategy.Default

为了知道是否应更新视图,Angular需要访问新值,将其与旧值进行比较,然后决定是否应更新视图。

默认情况下,Angular不会假设组件依赖什么。因此,它必须是保守的,并且在每次可能发生更改时都会进行检查,这称为脏检查(dirty checking)。更具体点说,它将对每个浏览器事件,计时器,XHR和Promise执行检查。

这可能会成为问题,当你开始开发一个包含许多组件的大型应用程序时,特别是如果你很关注性能。

默认情况下,Angular必须保持保守,并且每当可能发生更改时都会进行检查,这称为脏检查。

ChangeDetectionStrategy.onPush

在组件上使用onPush策略时,你会对Angular说,当需要执行变更检测时,它不应进行任何猜测。它仅依赖于Input引用的更改,一些由组件自身或子组件触发的事件。最后,你可以明确地要求Angular使用componentRef.markForCheck()方法执行此操作。

使用onPush,该组件只依赖于Input,并且拥有不变性(embraces the immutability,应该就是说只依赖于Input引用的更新),变更检测策略将在以下情况下执行:

  1. Input 引用更新;
  2. 由组件或其子组件触发的事件;
  3. 明确执行变更检测componentRef.markForCheck();
  4. 在视图中使用async管道。

使用onPush,Angular将仅依赖于组件的输入,事件,markForCheck方法或模板中异步管道的使用来执行变更检测机制并更新视图。

这样可以大大提高性能,Angular不会做任何猜测或毫无用处的工作。它通过其组件使您的应用程序具有不变性。


原文出处
Angular Change Detection Strategy: An introduction

更深入学习

  1. Everything you need to know about change detection in Angular
  2. Change Detection in Angular
  3. Essential Angular: Change Detection
  4. 🚀 A Comprehensive Guide to Angular onPush Change Detection Strategy