Angular 变更检测探究

老门东

引言

使用过现代JavaScript框架的开发者,都应该熟悉绑定(binding)的概念。绑定通常有两个方向。一是由用户交互驱动,在浏览器的页面上发生了输入、点击操作,导致应用程序的状态发生改变,这些改变需要反映到程序中特定变量上。另一个方向是,JavaScript代码的业务逻辑中改变了程序的状态,比如通过API请求拿到新的数据,而这些状态也需要反映的页面的控件上。很多框架如AngularJS就实现了双向绑定机制。

下面我们来看上述第二种绑定,即程序状态从业务代码到前端页面的传递过程。如果沃恩自己去实现应该怎么做呢?最直观的想法是:在恰当的时候对程序中的变量表达式进行求值,看看它是否与原来的值相同。如果不同,则把新的值写入与页面渲染相关的对象中。这里面检查变量表达式的值是否变化的过程就是所谓的变更检测(change detection)。Angular就是采用变更检测实现绑定的。下面我们具体来看。

基本原理

程序状态变化的来源有以下几种,首先是响应用户在UI上的操作,比如用户点击了一个按钮,改变了某个变量的值。然后是浏览器的异步事件,比如setTimeout的回调函数,改变了某个变量。最后是应用程序中的异步事件,比如API返回的Promise或者Observable对象在Resolve时,改变了变量的值。那么Angular是如何知道这些状态的改变呢?

我们知道,Angular的组件可以依赖其他的组件来构建应用程序的页面逻辑,最后形成一棵组件树。每个组件都有自己的变更检测器(change detector)。因此,变更检测器的结构也是一棵同构的树(见下图)。
变更检测器树

当某个组件的状态发生改变时,Angular会从这棵树的根节点开始遍历,出发所有组件节点的变更检测器,这样Angular就知道那些组件的状态发生了改变,需要更新相应的UI(见下图)。这个过程看似开销很大,但Angular已经进行了大量优化,实际变更检测的速度很快。

默认变更检测策略

上述变更检测的策略是Angular的默认行为。事实上,我们可以通过ChangeDetectionStrategy对象来配置某个组件的变更检测策略。如果不指定,该对象的值是Default。在默认情况下,某个组件的变更检测触发,受其他组件的影响。那么如何让组件只关注自己的内部的变化呢?答案是设置ChangeDetectionStrategy的值为OnPush

OnPush策略

在OnPush策略下,只有两种情况可以触发当前组件的变更检测:

  • 组件的输入属性(绑定)的引用被改变
  • 组件内部触发了异步事件

我们先来看第一点,这里关键词是引用。比如下面这个组件:

@Component({
   
  template: `
    <test [config]="config"></test>
  `
})
export class AppComponent  {
   
  config = {
   
    name: 'jtz'
  };
  onClick() {
   
    this.config.name = 'code';
  }
}

我们在

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值