angular 2+ 变化检测系列三(Zone.js在Angular中的应用)
在系列一中,我们提到Zone.js,Zones是一种执行上下文,它允许我们设置钩子函数在我们的异步任务的开始位置和结束位置,Angular正是利用了这一特性从而实现了变更检测。
Zones.js非常适合Angular
事实证明,Zones解决的问题非常适合Angular在我们的应用程序中执行变更检测所需的内容。你有没有问过自己Angular何时以及为何进行变化检测?什么时候告诉Angular: 兄弟,我的应用程序中可能发生了一个变化。你能检查一下吗?在我们深入研究这些问题之前,让我们首先考虑一下应用程序中实际导致这种变化的原因。或者更确切地说,在我们的应用程序中可以改变状应用程序状态更改由三种情况引起:
- Events - 用户事件比如
click,change,input,submit, … - XMLHttpRequests - 比如从远程服务器获取数据
- Timers -
setTimeout(),setInterval()
你可能发现了:这三种情况都是异步的.这是Angular实际上对更新视图感兴趣的唯一情况。假设我们有一个Angular组件,当单击一个按钮时它会执行一个处理程序
@Component({
selector: 'my-component',
template: `
<h3>We love {{name}}</h3>
<button (click)="changeName()">Change name</button>
`
})
class MyComponent {
name:string = 'thoughtram';
changeName() {
this.name = 'Angular';
}
}
单击组件的按钮时,将执行changeName(),这将更改组件的name属性。由于我们希望此更改也反映在DOM中,因此Angular将相应地更新视图绑定{{name}}。很好,这似乎神奇地工作。
另一个例子是使用setTimeout()更新name属性。请注意,我们删除了该按钮。
@Component({
selector: 'my-component',
template: `
<h3>We love {{name}}</h3>
`
})
class MyComponent implements OnInit {
name:string = 'thoughtram';
ngOnInit() {
setTimeout(() => {
this.name = 'Angular';
}, 1000);
}
}
我们没有一些特别操作,Angular自动帮我们做了变化检测.
实际上,告诉Angular在VM完成任务时执行更改检测的代码就像这样简单:
ObservableWrapper.subscribe(this.zone.onTurnDone, () => {
this.zone.run(() => {
this.tick();
});
});
tick() {
// perform change detection
this.changeDetectorRefs.forEach((detector) => {
detector.detectChanges();
});
}
每当Angular的区域发出onTurnDone事件时,它就会运行一个任务,对整个应用程序执行更改检测。但是等一下,onTurnDone事件发射器来自哪里?这不是默认Zone.js API的一部分,对吧?事实证明,Angular引入了自己的名为NgZone的区域。
Angular中的NgZone
NgZone基本上是一个分叉区域,它扩展了它的API并为其执行上下文添加了一些额外的功能。它添加到API中的一件事是我们可以订阅的以下一组自定义事件,因为它们是可观察的流:
- onTurnStart() - 在Angular事件开始之前通知订阅者。每个由Angular处理的浏览器任务发出一次事件。
- onTurnDone() - 在Angular的区域完成后处理当前事件队列以及从事件队列的任何微任务后立即通知订阅者。
- onEventDone() - 在结束VM事件之前,在最终的onTurnDone()回调之后立即通知订阅者。用于测试以验证应用程序状态。
Angular添加自己的事件发射器而不是依赖于beforeTask和afterTask回调的主要原因是它必须跟踪定时器和其他微任务。将Observable用作处理这些事件的API也很不错。
在Angular区域外运行代码
因为NgZone实际上是全局区域的一个分支,所以Angular可以完全控制代码什么时候在其区域内进行变更检测,什么时候不能.为什么这有用?好吧,事实证明我们并不总是希望Angular能够神奇地执行变化检测。
正如前面提到的那样,Zones几乎可以通过浏览器修补任何全局异步操作。由于NgZone只是该区域的一个分支,它通知框架在异步操作发生时执行变更检测,因此当mousemove事件触发时它也会触发变更检测。我们可能不希望每次触发mousemove时都执行更改检测,因为它会降低我们的应用程序速度并导致非常糟糕的用户体验。
这就是为什么NgZone带有一个API runOutsideAngular(),它在NgZone的父区域中执行给定任务,该区域不会发出onTurnDone事件,因此不会执行更改检测。为了演示这个有用的功能,我们来看看下面的代码:
@Component({
selector: 'ng-zone-demo',
template: `
<p>Progress: {{progress}}%</p>
<p *ngIf="progress >= 100">Done processing {{label}} of Angular zone!</p>
<button (click)="processWithinAngularZone()">Process within Angular zone</button>
<button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
`
})
export class NgZoneDemoComponent {
progress: number = 0;
label: string;
constructor(private _ngZone: NgZone) {}
// Loop inside the Angular zone
// so the UI DOES refresh after each setTimeout cycle
processWithinAngularZone() {
this.label = 'inside';
this.progress = 0;
this._increaseProgress(() => console.log('Inside Done!'));
}
// Loop outside of the Angular zone
// so the UI DOES NOT refresh after each setTimeout cycle
processOutsideOfAngularZone() {
this.label = 'outside';
this.progress = 0;
this._ngZone.runOutsideAngular(() => {
this._increaseProgress(() => {
// reenter the Angular zone and display done
this._ngZone.run(() => { console.log('Outside Done!') });
});
});
}
_increaseProgress(doneCallback: () => void) {
this.progress += 1;
console.log(`Current progress: ${this.progress}%`);
if (this.progress < 100) {
window.setTimeout(() => {
this._increaseProgress(doneCallback);
}, 10);
} else {
doneCallback();
}
}
}
angular 2+ 变化检测系列三(Zone.js在Angular中的应用)的更多相关文章
- angular 2+ 变化检测系列一(基础概念)
什么是变化检测? 变化检测的基本功能就是获取应用程序的内部状态(state),并且是将这种状态对用户界面保持可见.状态可以是javascript中的任何的数据结构,比如对象,数组,(数字,布尔,字符串 ...
- angular 2+ 变化检测系列二(检测策略)
我们将创建一个简单的MovieApp来显示有关一部电影的信息.这个应用程序将只包含两个组件:显示有关电影的信息的MovieComponent和包含执行某些操作按钮的电影引用的AppComponent. ...
- Angular开发实践(三):剖析Angular Component
Web Component 在介绍Angular Component之前,我们先简单了解下W3C Web Components 定义 W3C为统一组件化标准方式,提出Web Component的标准. ...
- zone.js - 暴力之美
在ng2的开发过程中,Angular团队为我们带来了一个新的库 – zone.js.zone.js的设计灵感来源于Dart语言,它描述JavaScript执行过程的上下文,可以在异步任务之间进行持久性 ...
- Zone.js 简介 & 抛砖引玉
Zone.js是angular团队参照NodeJS的Domain,Dart的Zone,为angular 2开发的核心组件. 一开始,我对Zone.js是拒绝的.我们知道类似的 Domain 模块,主要 ...
- Angular build Error:In this configuration Angular requires Zone.js
Angular cli 运行 build后打开生成的index.html报错:In this configuration Angular requires Zone.js 生成代码如下: ng bui ...
- Angular 个人深究(三)【由Input&Output引起的】
Angular 个人深究(三)[由Input&Output引起的] 注:最近项目在做别的事情,angular学习停滞了 1.Angular 中 @Input与@Output的使用 //test ...
- 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp专家
系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...
- Web 开发人员和设计师必读文章推荐【系列三十】
<Web 前端开发精华文章推荐>2014年第9期(总第30期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...
随机推荐
- kotlin电商学习记录,好久没来逛逛了
好久没来,一直做毕业设计,用kotlin写一个基于以图搜图的购物app,现在又赶上实习,内容多,时间少,不过前途光明并由贵人指点.加油 kotlin电商学习记录 技术选型 视图层 kotlin-and ...
- 数据分析---《Python for Data Analysis》学习笔记【02】
<Python for Data Analysis>一书由Wes Mckinney所著,中文译名是<利用Python进行数据分析>.这里记录一下学习过程,其中有些方法和书中不同 ...
- BATCH+VBS脚本自动执行命令
打开cmd,然后执行run.bat s 1就会执行tmpsw.vbs的内容,1是作为id传进去的参数. run.bat: @echo off set type=%1 set id=%2 :打开一个te ...
- [欢乐向]JavaScript之如何逼疯你的同事
https://javascript.info/ninja-code
- 金融量化分析【day110】:Pandas的Series对象
一.pandas简介安装 pandas是一个强大的python数据分析的工具包 pandsa是基于NumPy构建的 1.pandas的主要功能 1.具备对其功能的数据结构DataFrame.Serie ...
- Object is not a function
如图报了一个这样的错,百度好多都说是函数名和html元素重名的问题.可是这个问题我想我这里是不存在的 可以看到就一个绑定事件,而且id名不是关键字 报错是在$.ajax这一行,索性就把submit-i ...
- 基于alpine制作php镜像
alpine包搜索https://pkgs.alpinelinux.org/ 安装依赖库 apk add --no-cache xxx 可以基于php apline镜像自行增加或删除扩展. https ...
- 第一节: Timer的定时任务的复习、Quartz.Net的入门使用、Aop思想的体现
一. 前奏-Timer类实现定时任务 在没有引入第三方开源的定时调度框架之前,我们处理一些简单的定时任务同时都是使用Timer类, DotNet中的Timer类有三个,分别位于不同的命名空间下,分别是 ...
- [数学笔记Mathematical Notes]目录
2.也许是一个问题,暂时没给出解答. 2015年7月5日 1. 这个一个笔记类型的数学杂志, 打算用来记录自己学数学时做的笔记,一般几页纸一期. 觉得有意思就摘抄下来,或者自己的感想. 可能有些不是原 ...
- [物理学与PDEs]第2章第2节 粘性流体力学方程组 2.4 粘性热传导流体动力学方程组
粘性热传导流体动力学方程组: $$\beex \bea \cfrac{\p \rho}{\p t}+\Div(\rho{\bf u})&=0,\\ \rho \cfrac{\rd {\bf u ...