当我们在使用 angular 框架搭建项目时,随着越来越多,页面也来越复杂,性能会越来越低,主要表现在 cpu 使用率 很高。所以我们要对项目做一定的优化。
angular 的脏检测主要是指 zone.js,这是一个开源的第三方库,github地址。
关于 zone.js 的定义,官方解释为:
a zone is an execution context that persists across async tasks, and allows the creator of the zone to observe and control execution of the code within the zone.
简单来说,一个 zone 可作为多个异步任务执行的上下文,并能够控制这些异步任务。详细可以查看这篇文章。
我们回归 angular 框架,angular 团队通过对 zone.js 封装,实现了 脏检查(change detection)机制。
当优化性能的时候,我们首先要考虑,哪些方面会影响程序的性能?总结主要有以下几点:
逻辑代码的复杂程度
这主要是受js/ts运算效率低的影响,所以项目中尽量减少使用js/ts做复杂运算。即使有 牛x 的 v8 引擎加持,还是要慎重,毕竟 javascript 是脚本语言,执行效率与生俱来的低,哪怕你可以用它写一个操作,哈哈哈!!
减少event handler
event handler的运行时间无疑对我们的性能有着重要的影响,比如 scrolbar和鼠标移动事件,窗口resize事件,这些都是触发频率很高的事件,极其影响性能,可以对其做 节流与 防抖,以提升性能。
dom 树复杂
如果你的项目是一个大型项目,且 dom元素错综复杂,那么你应该考虑如何拆解并将其组件化。
angular dom视图更新
大家都知道, angular的牛逼之处就是友好的双向绑定机制,但是绑定的值何时发生变化?何时更新?这也是这篇文章要达到的目的。
接下来我们简单介绍一下 脏检测(change detection),简称 cd。angular 默认是脏检查方法是从根组件开始,遍历所有的子组件进行脏检查。我们看一个 检测前 和 检测时 的模型。
脏检测之前:
图中为组件树
变化检测时:
那么何时触发脏检测?主要有以下几个方面:
ajax请求 timeout 延迟事件 鼠标事件触发脏检测的目的就是 检测视图(dom) 有没有发生变化,方法就是比较 双向绑定中 view 和 model 是否一致。
可能看到这的童鞋还是有一些晕叉叉,接下来我们通过一个例子来分析。
ng new testzone
创建一个子组件 view:
ng g c viewview.component.html文件
{{user.getname()}}
import { component, input, docheck } from '@angular/core'; @component({ selector: 'app-view', templateurl: './view.component.html', styleurls: ['./view.component.css'], changedetection: changedetectionstrategy.onpush }) export class viewcomponent implements docheck { @input() user: any; index = 0; constructor() { } ngdocheck() { this.index++; console.log('view被执行', this.index); } }修改app.component.ts组件
import { component, docheck } from '@angular/core'; class user { _age = 25; _name = 'vincent'; getage() { console.log('执行获取age'); return this._age; } getname() { console.log('执行获取name'); return this._name; } } @component({ selector: 'app-root', templateurl: './app.component.html', styleurls: ['./app.component.css'] }) export class appcomponent implements docheck { index = 0; user = new user; change() { } ngdocheck() { this.index++; console.log('app被执行', this.index); } }app.component.html
click运行
npm start访问 https://localhost:4200/
import { component, oninit, input, docheck, changedetectionstrategy } from '@angular/core'; @component({ selector: 'app-view', templateurl: './view.component.html', styleurls: ['./view.component.css'], changedetection: changedetectionstrategy.onpush }) export class viewcomponent implements oninit, docheck { @input() user: any; index = 0; constructor() { } ngoninit() { } ngdocheck() { this.index++; console.log('view被执行', this.index); } }重新运行结果如图:
ng g s view/view内容为:
import { injectable } from '@angular/core'; import { subject } from 'rxjs'; @injectable({ providedin: 'root' }) export class viewservice { subject = new subject(); constructor() { } send(count: number) { this.subject.next(count); } }修改app.component.ts和app.component.html
import { component, docheck } from '@angular/core'; import { viewservice } from './view/view.service'; @component({ selector: 'app-root', templateurl: './app.component.html', styleurls: ['./app.component.css'] }) export class appcomponent implements docheck { index = 0; constructor(private viewservice: viewservice) { } change() { this.viewservice.send(100); } ngdocheck() { this.index++; console.log('app被执行', this.index); } }
click修改view.component.ts和view.component.html
import { component, oninit, docheck, changedetectionstrategy } from '@angular/core'; import { viewservice } from './view.service'; @component({ selector: 'app-view', templateurl: './view.component.html', styleurls: ['./view.component.css'], changedetection: changedetectionstrategy.onpush }) export class viewcomponent implements oninit, docheck { index = 0; count = 0; constructor(private viewservice: viewservice) { this.viewservice.subject.asobservable().subscribe( (count) => { this.count = count; } ); } ngoninit() { } ngdocheck() { this.index++; console.log('view被执行', this.index); } }
{{count}}
import { component, oninit, docheck, changedetectionstrategy, changedetectorref } from '@angular/core'; import { viewservice } from './view.service'; @component({ selector: 'app-view', templateurl: './view.component.html', styleurls: ['./view.component.css'], changedetection: changedetectionstrategy.onpush }) export class viewcomponent implements oninit, docheck { index = 0; count = 0; constructor(private viewservice: viewservice, private cdref: changedetectorref) { this.viewservice.subject.asobservable().subscribe( (count) => { this.count = count; this.cdref.detectchanges(); } ); } ngoninit() { } ngdocheck() { this.index++; console.log('view被执行', this.index); } }重新运行后,点击 按钮发生了变化。
如对本文有疑问, 点击进行留言回复!!
css深入剖析transform的translate和perspective
HCIE第四天总结(典型组网之一:CSS+Eth-Trunk+iStack)
了解下Apache Elasticsearch 和 Kibana
网友评论