angular input_Angular之性能优化-OnPush 和 NgZone

Angular性能优化

变化检测

Angular 对比 AngularJS 在变化检测上由原来的双向检测(父->子,子->父)变为了单向(父->子)。所以每一次变化检测都会确定性地收敛,一般页面即使有几千个组件,变化检测也可以做几毫秒内完成,所以大家开发时很少会遇到性能瓶颈。(即使是AngularJS也很少遇到瓶颈)

e9837c06ee6a12ad370267cac9f6fffd.png

自然很多开发者其实对Angular变化检测不会去深入了解。什么是变化检测?Angular在什么时候会进行变化检测呢?

a0c5304d5347ec51ca19885b231eb0da.png

变化检测定义:检测组件模型的变化并重绘制对应的View。比如:按钮颜色变化了 -> 重绘制按钮。

例子:优化绘制10000 svg rect

@Component

用onpush strategy进行性能提升

定义一个组件时,可以传入一个变化检测配置项为

changeDetection: 

配置为默认变化检测组件会判断输入的值是否改变来决定是否重渲染当前的view,box组件的判断逻辑为

if 

在不需要优化性能的时候,这样的变化检测判断完全没有问题。但10000个svg的变化检测耗时显然需要优化,这时候我们可以用onpush策略来减少变化检测的开销。onpush策略只判断输入的引用(如果是object)是否改变

if 

这边发现一下子减少了两个比较操作。对于10000个svg来说,就是少了20000个比较操作。

代码变化:

// parent

利用ngzone优化

回到一开始的问题,什么时候进行变化检测?

  • Events - User events like click, change, input, submit, …
  • XMLHttpRequests - E.g. when fetching data from a remote service
  • Timers - setTimeout(), setInterval(), because JavaScript

都是异步操作。异步操作引发模型变化,从而触发重渲染动作。Angular依赖NgZone来监听异步操作,并从根部执行变化检测。

ObservableWrapper

这个svg例子中,每次拖拽改变的是box的坐标,我们可以通过暂时禁用变化检测来优化。box坐标通过直接改变box元素的属性来实现。

mouseDown

数据:

不优化:11-14fps mouse move cost: 52-56 ms

Onpush优化:16-21fps mouse move cost: 24-30ms

Ngzone优化:35-45fps mouse move cost: ~0.5ms

代码:

kingfolk/Angular-Playground

reference

Making your Angular apps fast by thoughtram​blog.thoughtram.io Zones in Angular​blog.thoughtram.io
05ce5d5b12fec1e8fda48d95a6818154.png
Using Zones in Angular for better performance​blog.thoughtram.io
681fcf79e9dd5152b053c141b124109f.png
人类身份验证 - SegmentFault​segmentfault.com Angular Change Detection Explained​blog.thoughtram.io
c0bdf5551978d5037e58c6c31b433975.png