深入分析 Angular 变更检测

Posted 前端那些事儿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入分析 Angular 变更检测相关的知识,希望对你有一定的参考价值。

目录

  • 什么是变更检测 (Change Dectetion)?

  • 什么引起了变更 (change) ?

  • 发生变更后,谁通知Angular?

  • 变更检测

  • 性能

  • 更聪明的变更检测

  • 不变对象 (Immutable Objects)

  • 减少检测次数 (number of checks)

  • Observables

  • 更多..

什么是变更检测

变更检测的基本任务是获得程序的内部状态并使之在用户界面可见。这个状态可以是任何的对象、数组、基本数据类型,..也就是任意的javascript数据结构。

这个状态在用户界面上最终可能成为段落、表格、链接或者按钮,并且特别对于 web 而言,会成为 DOM 。所以基本上我们将数据结构作为输入,并生成 DOM 作为输出并展现给用户。我们把这一过程成为rendering(渲染)



然而,当变更发生在 runtime 的时候,它会变得很奇怪。比如当 DOM 已经渲染完成以后。我们要如何知悉 model 中什么发生了改变,以及更新 DOM 的什么位置?
访问DOM树是十分耗时的,所以我们不仅要找到应该更新 DOM 的位置,并且要尽可能少地访问它。



这个问题有许多解决方法。比如其中一个方法是简单地通过发送http请求并重新渲染整个页面。另一个方法是 ReactJs 提出的 Virtual Dom 的概念,即检测 DOM 的新状态与旧状态的不同并渲染其不同的地方。

Tero 写了一篇很棒的文章,是关于 Change and its detection in JavaScript frameworks,即不同JavaScript框架之间的变更检测,如果你对于这个问题感兴趣的话我建议你们去看一看。在这篇文章中我会专注于Angular>=2.x的版本。

什么引起了变更(change)?

既然我们知道了变更检测是什么,我们可能会疑惑:到底这样的变更什么时候会发生呢?Angular 什么时候知道它必须更新 view 呢?好吧,我们来看看下面的代码:

@Component({
  template: `
    <h1>{{firstname}} {{lastname}}</h1>
    <button (click)="changeName()">Change name</button>
  `
})
class MyApp {

  firstname:string = 'Pascal';
  lastname:string = 'Precht';  changeName() {
    this.firstname = 'Brad';
    this.lastname = 'Green';
  }
}

如果这是你第一次看Angular组件,你可能得先去看看 如何写一个tabs组件

上面这个组件简单地展示了两个属性,并提供了一个方法,在点击按钮的时候调用这个方法来改变这两个属性。这个按钮被点击的时候就是程序状态已经发生了改变的时候,因为它改变了这个组件的属性。这就是我们需要更新视图(view)的时候。

下面是另一个例子:

以上是关于深入分析 Angular 变更检测的主要内容,如果未能解决你的问题,请参考以下文章

Angular中的变更检测

Angular 5.0 变更检测策略 VS React 的变更检测策略

angular变更检测和onPush策略

如何在 Angular2 中触发变更检测? [复制]

我在 Angular 变更检测中的断点未在 checkAndUpdateView() 上触发

Angular2 生命周期钩子方法中的变更检测