ここでangularのドキュメントを確認しましたが、完全に理解することはできませんでした。
NgZone
は、非同期関数を追跡可能にするために非同期関数のコンテキストを作成するライブラリであるZone.jsのラッパーです。
Angularの変更検出はZones
に大きく依存しています、どうやって?
Angularには、変更検出を実行するタイミングを理解する方法が必要です。これは基本的に、最新のモデル(javascript)の変更を表すためにDOM
を更新することに他なりません。
以下の例があると想像してください:
_ <div id="content"></div>
_
そして、JavaScriptコードのどこかに、
_const element = document.getElementById('content');
function updateText(){
element.innerHtml = myText+ ": updated at time"+Date.now()
}
_
最初にcontent
をhelloで更新するとしましょう:
_ const myText = "Hello";
this.updateText();
_
これにより、HTMLコンテンツが次のテキストに更新されます:「こんにちは、19:30に更新されました」
次に、ユーザーがクリックした後、myText
変数を別の変数に更新するとします。
_ <button onClick="updateTheTextAgain()"></button>
updateTheTextAgain(){
this.myText = "Hi there";
}
_
そのボタンをクリックするとどうなりますか?
なし;
実は、「何もない」というわけではなく、変数を更新することができましたが、ビューを更新しなかった(モデルの変更を検出しなかった)ので、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
_を通過します。つまり、私はclick
イベントハンドラー自体に組み込まれているため、クリックするたびにupdateText()
関数を実行する必要はありません。
Angularでは、そのupdateText
は_change detection
_であり、Angularはすべてのネイティブイベントにフックを持っています(ゾーンを使用)。
だからあなたが書くとき:
_ setTimeout(()=>{
console.log('Do something');
},100);
_
あなたが実際に書いているのは次のようなものです:
_ setTimeout(()=>{
console.log('Do something');
runAngularsChangeDetection();
},100);
_
上記は実際に起こっていることとはかけ離れていますが、それは変更検出とZones
の全体像の中心であり、なぜそれらが必要なのですか/
**更新:**
いつNgZone
を使用する必要があります。
NgZone
を使用したい場合はたくさんありますが、2つ挙げることができます。
1- Angularの変更検出の外で何かを実行したい場合:
Angularはすべての非同期イベントにフックがありますか?_window.onScroll
_はその1つです。ここで、ユーザーがスクロールしているときに計算を実行したいとします。通常は次のようにします。 :
_ window.onscroll = ()=>{
// do some heavy calculation :
}
_
これで、スクロールすると、期待どおりに関数が正常に呼び出されますが、パフォーマンスの問題が少し発生していることに気付く場合があります。これは、AngularがchangeDetection
すべてのスクロールイベント(予想される動作)。
コンポーネントに多くのバインディングがある場合は、スクロールのパフォーマンスが低下していることに間違いなく気付くでしょう。
つまり、1つの方法は、Angularさん、私のonscroll
イベントを無視することです。私が何をしているのかはわかっています。変更検出を実行したくないので、この場合はNgZone
_ constructor(private zone:NgZone){
this.zone.runOutsideOfAngular(()=>{
window.onscroll = ()=>{
// do some heavy calculation :
}
})
}
_
これにより、Angularがスクロール時に変更検出を実行しないようになります。
もう1つのケースは、上記とは正反対です。たとえば、サードパーティのライブラリが何かを行っていて、それにバインドしたい場合のように、Angularのゾーンの外側にある関数があり、それを内側にしたい場合です。あなたのAngularサイクル。
_ this.zone.run(()=>{
$.get('someUrl').then(()=>{
this.myViewVariable = "updated";
})
});
_
ゾーンを使用せずに、次のことを行う必要があります。
_ $.get('someUrl').then(()=>{
this.myViewVariable = "updated";
this.changeDetectorRef.detectChanges();
})
_
ただし、関数がゾーン内にある場合(runメソッド)、手動でdetectChanges
を呼び出す必要はなく、angularがその仕事をします。
現在の公式文書は基準に達していません。 Angularでクレイジーなことをする人がいますPascal Precht。以下の記事は、Zone
とngZone
が何であるかを理解するのに役立ちます。
https://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html