angular 中的区域
Zones in angular
- 什么是区域?
- angular ngZone 与 zone.js 有何不同?
- 什么时候用?有人可以帮助提供使用 ngZone 的实际示例吗?
我已经阅读了这里的 angular 文档,但是我无法完全理解。
目前官方文档不合格。在 Angular 中有人做疯狂的事情 Pascal Precht 也是如此。他的以下文章将帮助您了解什么是 Zone
和 ngZone
。
https://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html
NgZone
是 Zone.js 的包装器,它是一个围绕异步函数创建上下文以使它们可跟踪的库。
Angular的变更检测严重依赖Zones
,如何?
Angular 需要一种理解何时 运行 变化检测的方法,基本上就是更新 DOM
以表示最新模型(javascript ) 变化。
假设我们有以下示例:
<div id="content"></div>
在我们的 javascript 代码的某处,我们有
const element = document.getElementById('content');
function updateText(){
element.innerHtml = myText+ ": updated at time"+Date.now()
}
假设最初我要更新 content
打个招呼:
const myText = "Hello";
this.updateText();
这会将我的 HTML 内容更新为文本:"Hello updated at time 19:30"
然后假设我想在用户单击后将 myText
变量更新为其他内容:
<button onClick="updateTheTextAgain()"></button>
updateTheTextAgain(){
this.myText = "Hi there";
}
如果我点击那个按钮会发生什么?
无;
嗯,实际上不是,"nothing",我设法更新了变量,但我没有更新视图(我没有检测到模型的变化),所以我需要调整我的 updateTheTextAgain
是:
updateTheTextAgain(){
this.myText = "Hi there";
this.updateText(); /// Making sure I'm detecting the change ( I'm updating the `DOM`)
}
现在,单击按钮将更新我的视图(因为手动更改检测)。
这显然不是最好的主意,因为那样的话我必须写很多updateText
函数并在我更新模型后在任何我希望更新视图的地方调用它们,对吧( 返回到 Angular1 并记住 $scope.apply()
)?
这就是 ZoneJs
令人惊叹的地方。
想象一下,如果我可以重写 onClick
函数,我的意思是浏览器的原始 onClick 函数是:
const originalOnClick = window.onClick;
window.onClick = function(){
originalOnClick();
this. updateText();
}
这称为本机函数的 monkey patching
或 open heart surgery
。
我得到了什么?
在我将 patched onClick
放入页面后,将要在整个应用程序中编写的所有 onClick
函数都将通过我的 patched onClick
,这意思是,我不必在每次点击后都执行 运行 updateText()
函数,因为它已融入 click
事件处理程序本身。
在Angular中,updateText
是change detection
,Angular在所有本地事件中都有挂钩(通过使用区域)。
所以当你写的时候:
setTimeout(()=>{
console.log('Do something');
},100);
你实际写的是这样的:
setTimeout(()=>{
console.log('Do something');
runAngularsChangeDetection();
},100);
以上与现实中发生的事情相去甚远,但它是整个变化检测故事的核心,Zones
以及我们为什么需要它们/
** 更新:**
什么时候应该使用NgZone
.
很多情况下你想使用NgZone
,我可以举出两个:
1- 当你想要在 Angular 的变化检测之外 运行 时:
记得我说过 Angular 在所有异步事件中都有挂钩吗? window.onScroll
是其中之一,现在假设我们想在用户滚动时进行一些计算,您通常做的是:
window.onscroll = ()=>{
// do some heavy calculation :
}
现在,当滚动时,您的函数会像您预期的那样正常调用,但您可能会注意到您遇到了一些性能问题,这可能是因为 Angular 是 运行在每个滚动事件(预期行为)上设置 changeDetection
。
如果您的组件中有很多绑定,那么您肯定会注意到滚动上的性能下降。
所以一种方法是说,嘿 Angular,忽略我的 onscroll
事件,我知道我在做什么,我不想让你 运行 更改检测,在这种情况下,您将使用 NgZone
constructor(private zone:NgZone){
this.zone.runOutsideOfAngular(()=>{
window.onscroll = ()=>{
// do some heavy calculation :
}
})
}
这将确保 Angular 不会 运行 滚动时更改检测。
另一种情况与上述情况完全相反,您有一个函数不知何故位于 Angular 的区域之外,并且您希望它位于内部,例如当第三方库正在做一些事情时适合您的东西,您希望它与您的 Angular 周期绑定。
this.zone.run(()=>{
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
})
});
如果不使用 Zone,您很可能需要这样做:
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
this.changeDetectorRef.detectChanges();
})
但请注意,当您的函数位于区域内(运行 方法)时,您不必自己手动调用 detectChanges
,angular 将完成这项工作
- 什么是区域?
- angular ngZone 与 zone.js 有何不同?
- 什么时候用?有人可以帮助提供使用 ngZone 的实际示例吗?
我已经阅读了这里的 angular 文档,但是我无法完全理解。
目前官方文档不合格。在 Angular 中有人做疯狂的事情 Pascal Precht 也是如此。他的以下文章将帮助您了解什么是 Zone
和 ngZone
。
https://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html
NgZone
是 Zone.js 的包装器,它是一个围绕异步函数创建上下文以使它们可跟踪的库。
Angular的变更检测严重依赖Zones
,如何?
Angular 需要一种理解何时 运行 变化检测的方法,基本上就是更新 DOM
以表示最新模型(javascript ) 变化。
假设我们有以下示例:
<div id="content"></div>
在我们的 javascript 代码的某处,我们有
const element = document.getElementById('content');
function updateText(){
element.innerHtml = myText+ ": updated at time"+Date.now()
}
假设最初我要更新 content
打个招呼:
const myText = "Hello";
this.updateText();
这会将我的 HTML 内容更新为文本:"Hello updated at time 19:30"
然后假设我想在用户单击后将 myText
变量更新为其他内容:
<button onClick="updateTheTextAgain()"></button>
updateTheTextAgain(){
this.myText = "Hi there";
}
如果我点击那个按钮会发生什么?
无;
嗯,实际上不是,"nothing",我设法更新了变量,但我没有更新视图(我没有检测到模型的变化),所以我需要调整我的 updateTheTextAgain
是:
updateTheTextAgain(){
this.myText = "Hi there";
this.updateText(); /// Making sure I'm detecting the change ( I'm updating the `DOM`)
}
现在,单击按钮将更新我的视图(因为手动更改检测)。
这显然不是最好的主意,因为那样的话我必须写很多updateText
函数并在我更新模型后在任何我希望更新视图的地方调用它们,对吧( 返回到 Angular1 并记住 $scope.apply()
)?
这就是 ZoneJs
令人惊叹的地方。
想象一下,如果我可以重写 onClick
函数,我的意思是浏览器的原始 onClick 函数是:
const originalOnClick = window.onClick;
window.onClick = function(){
originalOnClick();
this. updateText();
}
这称为本机函数的 monkey patching
或 open heart surgery
。
我得到了什么?
在我将 patched onClick
放入页面后,将要在整个应用程序中编写的所有 onClick
函数都将通过我的 patched onClick
,这意思是,我不必在每次点击后都执行 运行 updateText()
函数,因为它已融入 click
事件处理程序本身。
在Angular中,updateText
是change detection
,Angular在所有本地事件中都有挂钩(通过使用区域)。
所以当你写的时候:
setTimeout(()=>{
console.log('Do something');
},100);
你实际写的是这样的:
setTimeout(()=>{
console.log('Do something');
runAngularsChangeDetection();
},100);
以上与现实中发生的事情相去甚远,但它是整个变化检测故事的核心,Zones
以及我们为什么需要它们/
** 更新:**
什么时候应该使用NgZone
.
很多情况下你想使用NgZone
,我可以举出两个:
1- 当你想要在 Angular 的变化检测之外 运行 时:
记得我说过 Angular 在所有异步事件中都有挂钩吗? window.onScroll
是其中之一,现在假设我们想在用户滚动时进行一些计算,您通常做的是:
window.onscroll = ()=>{
// do some heavy calculation :
}
现在,当滚动时,您的函数会像您预期的那样正常调用,但您可能会注意到您遇到了一些性能问题,这可能是因为 Angular 是 运行在每个滚动事件(预期行为)上设置 changeDetection
。
如果您的组件中有很多绑定,那么您肯定会注意到滚动上的性能下降。
所以一种方法是说,嘿 Angular,忽略我的 onscroll
事件,我知道我在做什么,我不想让你 运行 更改检测,在这种情况下,您将使用 NgZone
constructor(private zone:NgZone){
this.zone.runOutsideOfAngular(()=>{
window.onscroll = ()=>{
// do some heavy calculation :
}
})
}
这将确保 Angular 不会 运行 滚动时更改检测。
另一种情况与上述情况完全相反,您有一个函数不知何故位于 Angular 的区域之外,并且您希望它位于内部,例如当第三方库正在做一些事情时适合您的东西,您希望它与您的 Angular 周期绑定。
this.zone.run(()=>{
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
})
});
如果不使用 Zone,您很可能需要这样做:
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
this.changeDetectorRef.detectChanges();
})
但请注意,当您的函数位于区域内(运行 方法)时,您不必自己手动调用 detectChanges
,angular 将完成这项工作