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 ...
随机推荐
- python 基本数据类型以及内置方法
一.数字类型 # 一.整型int # ======================================基本使用====================================== ...
- Atcoder Beginner Contest 124 解题报告
心态爆炸.本来能全做出来的.但是由于双开了Comet oj一个比赛,写了ABC就去搞那个的B题 还被搞死了. 回来写了一会D就过了.可惜比赛已经结束了.真的是作死. A - Buttons #incl ...
- luogu P1250 种树
我来总结一下最常用的两种办法 1.贪心 2.差分约束 那么我们先来讲,贪心版<种树> 大家可能知道有一个题和这个类似,那个是钉钉子而这个是种树 我们可以借用钉钉子的思路来想,首先这个是让你 ...
- java querydsl使用
1 POM文件 <?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apa ...
- 洛谷P3205 [HNOI2011]合唱队 DP
原题链接点这里 今天在课上听到了这个题,听完后觉得对于一道\(DP\)题目来说,好的状态定义就意味着一切啊! 来看题: 题目描述 为了在即将到来的晚会上有更好的演出效果,作为AAA合唱队负责人的小A需 ...
- 剑指Offer_编程题_20
题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. /* struct TreeNode { int val; struct TreeNode *left; struct TreeN ...
- 使用catboost解决ML中高维度不平衡数据集挑战的解决方案
python风控评分卡建模和风控常识(博客主亲自录制视频教程) https://study.163.com/course/introduction.htm?courseId=1005214003&am ...
- 前端面试题整理—jQuery篇
1.为什么使用jquery,他有哪些好处? 1)轻量级.代码简洁 2)强大的选择器,出色的DOM操作封装 3)有可靠的事件处理机制 4)浏览器兼容性好 5)支持链式操作 6)支持丰富的插件 2.jqu ...
- SpringBoot系列: CommandLineRunner接口的用处
========================================使用 CommandLineRunner 对Spring Bean进行额外初始化==================== ...
- [物理学与PDEs]第1章第5节 Maxwell 方程组的数学结构, 电磁场的波动性 5.3 电磁场的波动性, 自由电磁波
1. 由 Maxwell 方程组易知 $$\beex \bea \cfrac{1}{c^2}\cfrac{\p^2{\bf E} }{\p t^2}-\lap{\bf E} &=-\sex{ ...