Mil*_*lad 26
NgZone
是Zone.js的包装器,它是一个库,它创建一个围绕异步函数的上下文,以使它们可跟踪.
Angular的变化检测严重依赖于Zones
,如何?
Angular需要一种了解何时运行更改检测的方法,这基本上只是更新DOM
代表最新模型(javascript)更改.
想象一下,我们有一个例子:
<div id="content"></div>
Run Code Online (Sandbox Code Playgroud)
在我们的javascript代码中,我们有
const element = document.getElementById('content');
function updateText(){
element.innerHtml = myText+ ": updated at time"+Date.now()
}
Run Code Online (Sandbox Code Playgroud)
我们先说我要用content
hello 更新它:
const myText = "Hello";
this.updateText();
Run Code Online (Sandbox Code Playgroud)
这会将我的HTML内容更新为文本:"Hello在19:30更新"
然后让我们说我想myText
在用户点击后将变量更新为其他内容:
<button onClick="updateTheTextAgain()"></button>
updateTheTextAgain(){
this.myText = "Hi there";
}
Run Code Online (Sandbox Code Playgroud)
如果我点击那个按钮会发生什么?
没什么 ;
好吧,实际上,它不是,"没什么",我设法更新变量,但我没有更新视图(我没有检测到模型的变化),所以我需要调整我的updateTheTextAgain
:
updateTheTextAgain(){
this.myText = "Hi there";
this.updateText(); /// Making sure I'm detecting the change ( I'm updating the `DOM`)
}
Run Code Online (Sandbox Code Playgroud)
现在,单击按钮将更新我的视图(因为手动更改检测).
这显然不是最好的主意,因为那时我必须编写很多updateText
函数并在我更新模型之后将它们调用到任何我希望更新的位置(对回Angular1并记住$scope.apply()
)?
这里ZoneJs
是惊人的地方.
想象一下,如果我可以重写onClick
函数,我的意思是浏览器的原始onClick函数是:
const originalOnClick = window.onClick;
window.onClick = function(){
originalOnClick();
this. updateText();
}
Run Code Online (Sandbox Code Playgroud)
这被称为monkey patching
或open heart surgery
本机功能.
我到底得到了什么?
在我把我patched onClick
放入页面之后,onClick
将要在整个应用程序中编写的所有函数都将通过我的patched onClick
,这意味着,我不必updateText()
在每次onclick之后再运行函数,因为它被烘焙到了click
事件处理程序本身
在角,即updateText
是change detection
,角在所有的本地事件钩(通过使用区域).
所以当你写:
setTimeout(()=>{
console.log('Do something');
},100);
Run Code Online (Sandbox Code Playgroud)
你实际写的是这样的:
setTimeout(()=>{
console.log('Do something');
runAngularsChangeDetection();
},100);
Run Code Online (Sandbox Code Playgroud)
以上是现实中发生的事情,但它是整个变化检测故事的核心,Zones
为什么我们需要它们/
**更新:**
我们什么时候应该使用NgZone
.
当你想要使用时会有很多情况NgZone
,我可以说出两个:
1-当你想要在Angular的变化检测之外运行时:
还记得我说Angular在所有异步事件中都有钩子吗?window.onScroll
是其中之一,现在假设我们想在用户滚动时进行一些计算,你通常做的是:
window.onscroll = ()=>{
// do some heavy calculation :
}
Run Code Online (Sandbox Code Playgroud)
现在,在滚动时,您的函数正如您所期望的那样正常调用,但您可能会注意到您遇到了一些性能问题,这可能是因为Angular正在运行changeDetection
每个滚动事件(预期行为).
如果你的组件中有很多绑定,那么你肯定会注意到滚动上的性能下降.
所以有一种方法就是说,嘿Angular,忽略我的onscroll
事件,我知道我在做什么,我不希望你运行变化检测,在这种情况下,你会使用NgZone
constructor(private zone:NgZone){
this.zone.runOutsideOfAngular(()=>{
window.onscroll = ()=>{
// do some heavy calculation :
}
})
}
Run Code Online (Sandbox Code Playgroud)
这将确保Angular不会在滚动时运行更改检测.
另一个案例与上面完全相反,你有一个函数在某种程度上在Angular的区域之外,你希望它在里面,就像第三方库为你做一些东西而你希望它被绑定到你的角度周期.
this.zone.run(()=>{
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
})
});
Run Code Online (Sandbox Code Playgroud)
不使用Zone,您很可能需要这样做:
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
this.changeDetectorRef.detectChanges();
})
Run Code Online (Sandbox Code Playgroud)
但请注意,当您的功能位于区域内(运行方法)时,您不必detectChanges
自己手动调用,而角度将完成工作
归档时间: |
|
查看次数: |
4638 次 |
最近记录: |