angular中利用zone避归没必要的开销提高程序的性能demo
在我们的最新文章中,我们讨论了如何通过探索Angular的ChangeDetectionStrategy
API以及如何分离变化探测器等技巧来使我们的Angular应用更快。虽然我们覆盖了许多不同的选项来提高演示应用程序的性能,但我们当然没有谈到所有可能的选择。
另一种选择是利用Zone API,在Angular Zone之外执行我们的代码,这将阻止Angular运行不必要的更改检测任务。他甚至投入时间和精力去创造一个展示如何做到这一点的演示。
在本文中,我们将探索他的普及,并解释如何使用Zone使我们的演示应用程序执行近60帧/秒
在我们直接进入代码之前,我们先来看看正在运行的应用程序的演示程序。作为一个快速回顾:这个想法是渲染10.000可拖动的SVG框。渲染10.000个盒子并不是一个非常复杂的任务,但是,挑战在于尽可能平滑拖拽的体验。换句话说,我们的目标是60 fps(每秒帧数),考虑到Angular在一个事件触发时(默认情况下)会重新渲染所有10.000个盒子,这确实很具挑战性。
- 这是一个优化前的实现:https://embed.plnkr.co/UBI5Sc5eDMpkDDkJfeGX
- 这是Jordi利用Angular的zone API 优化后的版本:https://embed.plnkr.co/GIf9sPuuZRLKwYK7mTfr
即使差异相当微妙,优化的版本在每帧的JavaScript执行方面表现也会更好。稍后我们会看看一些数字,但是让我们快速回顾Zones,然后深入代码并讨论Jordi如何使用Angular的NgZone
API来首先实现这种性能
Zone
在我们使用Zone API,特别是Angular的API之前NgZone
,我们需要了解Zone的实际情况,这里有两篇文章:
- 了解Zone
- Angular中的Zone
Zones打包异步浏览器API,并在异步任务已经开始或结束时通知消费者。Angular利用这些API在任何异步任务完成时得到通知。这包括诸如XHR
电话,setTimeout()
和几乎所有的用户事件,比如click
,submit
,mousedown
,...等等。
一旦通知,Angular知道它必须执行更改检测,因为任何异步操作可能已经改变了应用程序状态。例如,当我们使用Angular的Http
服务从远程服务器获取数据时,情况总是如此。以下片段显示了这样的调用如何改变应用程序状态:
@Component(...) export class AppComponent {data: any;//initial application state constructor(private dataService: DataService) {}ngOnInit() {this.dataService.fetchDataFromRemoteService().subscribe(data =>{this.data = data //application state has changed, change detection needs to run now });} }
关于这一点的好处是我们作为开发人员不必关心通知Angular执行更改检测,因为Zones会为我们做Angular订阅它们。
好的,现在我们谈谈这个问题,让我们来看看如何使用它们来快速构建我们的演示程序。
我们知道,只要发生异步事件并将事件处理程序绑定到该事件,就会执行更改检测。我们来看一下AppComponent
模板:
Component({...template: `<svg (mousedown)="mouseDown($event)"(mouseup)="mouseUp($event)"(mousemove)="mouseMove($event)"><svg:g box *ngFor="let box of boxes" [box]="box"></svg:g></svg> ` }) class AppComponent {... }
3个事件处理程序绑定到外部的SVG元素。当这些事件中的任何一个触发并且它们的处理程序已经被执行时,则执行改变检测。实际上,这意味着Angular会运行变化检测,即使我们只是将鼠标移动到框上而不实际拖动一个box!
这是利用NgZone
APIs派上用场的地方了。NgZone
使我们能够明确地运行Angular的区域以外的某些代码,防止Angular运行任何变化检测。所以基本上,处理程序仍然会被执行,但是由于它们不会在Angular的区域内运行,Angular将不会得到任务完成的通知,因此不会执行变更检测。一旦我们释放我们正在拖动的方框,我们只想运行变化检测。
好的,我们如何做到这一点?我们所要做的就是确保mouseMove()
事件处理程序只在Angular的区域之外被附加和执行。除此之外,我们知道只有在选择一个框进行拖动时,我们才会附加该事件处理程序。换句话说,我们需要更改我们的mouseDown()
事件处理程序,以便将事件侦听器强制添加到文档中。
以下是这个样子:
import { Component, NgZone } from '@angular/core';@Component(...) export class AppComponent {...element: HTMLElement;constructor(private zone: NgZone) {}mouseDown(event) {...this.element =event.target;this.zone.runOutsideAngular(() =>{window.document.addEventListener('mousemove', this.mouseMove.bind(this));});}mouseMove(event) {event.preventDefault();this.element.setAttribute('x', event.clientX + this.clientX + 'px');this.element.setAttribute('y', event.clientX + this.clientY + 'px');} }
我们在事件处理程序中注入NgZone
和调用,runOutsideAngular()
在这个mouseDown()
事件处理程序中附加事件的事件处理程序mousemove
。这确保mousemove
事件处理程序确实只在选定框时附加到文档。此外,我们保存到点击框的基本DOM元素的引用,所以我们可以更新它的x
和y
在属性mouseMove()
方法。我们正在处理DOM元素,而不是绑定了x
和的box对象y
,因为我们在Angular的区域之外运行代码,绑定不会被检测到。换句话说,我们不更新DOM,所以我们可以看到box是移动的,但是我们实际上还没有更新box。
另外请注意,我们mouseMove()
从组件的模板中删除了绑定。我们也可以删除mouseUp()
处理程序,并强制附加它,就像我们mouseMove()
处理程序一样。但是,它不会增加性能方面的任何价值,所以我们决定为了简单起见将其保留在模板中:
<svg(mousedown)="mouseDown($event)"(mouseup)="mouseUp($event)"><svg:gbox *ngFor="let box of boxes"[box]="box"></svg:g></svg>
在接下来的步骤中,我们要确保每当我们释放一个box(mouseUp
)时,我们更新box模型,再加上,我们想要执行变化检测,以便模型再次与视图同步。很酷的事情NgZone
不仅仅是它允许我们在Angular的Zone以外运行代码,它还提供了在Angular Zone 内部运行代码的API ,最终会导致Angular再次执行变化检测。我们所要做的就是打回调NgZone.run()
给它应该执行的代码。
这里是我们更新的mouseUp()
事件处理程序:
@Component(...) export class AppComponent {...mouseUp(event) {//Run this code inside Angular's Zone and perform change detectionthis.zone.run(() =>{this.updateBox(this.currentId, event.clientX + this.offsetX, event.clientY + this.offsetY);this.currentId = null;});window.document.removeEventListener('mousemove', this.mouseMove);} }
具体表现
优化前
优化后
结论
使用区域是摆脱Angular变化检测的好方法,不需要分离变化检测器,也不会使应用程序代码过于复杂。事实上,事实证明,Zones API非常易于使用,特别是NgZone
在Angular外部或内部运行代码的API。根据这些数字,我们甚至可以说这个版本与我们之前文章中提出的最快解决方案一样快。考虑到开发人员在使用Zones API时的体验要好得多,因为它比使用手动分离和重新连接更改探测器引用更容易使用,这绝对是迄今为止最“美观”的性能改进。
转载于:https://www.cnblogs.com/nanguabushuohua/p/8359089.html
angular中利用zone避归没必要的开销提高程序的性能demo相关推荐
- java聊天室小程序论文_在Java项目中利用continue与break制作一个聊天室小程序
在Java项目中利用continue与break制作一个聊天室小程序 发布时间:2020-12-08 16:03:27 来源:亿速云 阅读:98 作者:Leah 在Java项目中利用continue与 ...
- 【中亦安图】清算/报表/日终跑批程序之性能优化案例(5)
第一章 技术人生系列 · 我和数据中心的故事(第五期)-清算/报表/日终跑批程序之性能优化案例(一) 中亦安图 | 2016-02-18 21:40 前言 不知不觉,技术人生系列·我和数据中心的故事来 ...
- 您需要了解有关Angular中的ng-template,ng-content,ng-container和* ngTemplateOutlet的所有信息...
It was one of those days when I was busy working on new features for my office project. All a sudden ...
- angular routerlink传递参数_[翻译]在 Angular 中使用 async-await 特性
在 Angular 中使用 async-await 特性 原文链接: https://medium.com/@balramchavan/using-async-await-feature-in-ang ...
- C#中利用Socket实现网络语音通信[初级版本]
现在时下的VOIP软件很多,比较有名的就是Skype,还有其它诸如UUcall.快门等等.它们提供的功能除了网络上的语音通话外,还可以与固定电话.手机等通话.在本篇中主要介绍利用C#实现语音通信的基本 ...
- delphi中利用Indy的TIdFtp控件实现FTP协议
2019独角兽企业重金招聘Python工程师标准>>> delphi中利用Indy的TIdFtp控件实现FTP协议版权声明:本文为博主原创文章,未经博主允许不得转载.现在很多应用都需 ...
- Asp.Net Core中利用Seq组件展示结构化日志功能
在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...
- android 应用切换动画,怎么在Android应用中利用Activity对动画进行切换
怎么在Android应用中利用Activity对动画进行切换 发布时间:2020-11-27 16:19:53 来源:亿速云 阅读:107 作者:Leah 今天就跟大家聊聊有关怎么在Android应用 ...
- 在SPA应用中利用JWT进行身份验证
版权声明:本文为博主chszs的原创文章,未经博主允许不得转载. https://blog.csdn.net/chszs/article/details/79639919 在SPA应用中利用JWT进行 ...
- python打乱数据集_在Keras中利用np.random.shuffle()打乱数据集实例
我就废话不多说了,大家还是直接看代码吧~ from numpy as np index=np.arange(2000) np.random.shuffle(index) print(index[0:2 ...
最新文章
- 快速提升页面性能的必备利器
- time.h 详细介绍
- 数据库创建表的时候长度的介绍
- AB1601GPIO不支持较高频率的脉冲中断
- LeetCode Algorithm 70. 爬楼梯
- django 中的render和render_to_response()和locals()
- Windows Server 2008终端服务详解系列5:用ISA 发布SH-TSG
- 2017.8.23创业项目方向
- Jenkins --SVN
- 16位和32位微处理器(3)——Pentium的先进技术
- Java基础学习总结(76)——Java异常深入学习研究
- ExpandListView onChildClickListener 失效
- P2044 [NOI2012]随机数生成器
- android开发学习——day3
- 正则表达式去除空格、符号,只保留中文、英文、数字
- 传智播客风清扬视频-------线程简介2
- Labview实现简单知乎日报客户端
- 开发一个可以查询并显示数据库内容的微信小程序
- 什么样的公司才需要办理ICP经营许可证?
- 进销存系统--ERP软件常用货物计量单位汇总