web-dev-qa-db-ja.com

angular

  1. ゾーンとは何ですか?
  2. angular ngZoneはzone.jsとどのように異なりますか?
  3. それらはいつ使用されるべきですか?誰かがngZoneの実際の使用例を手伝ってもらえますか?

ここでangularのドキュメントを確認しましたが、完全に理解することはできませんでした。

https://angular.io/api/core/NgZone

11

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がその仕事をします。

30
Milad

現在の公式文書は基準に達していません。 Angularでクレイジーなことをする人がいますPascal Precht。以下の記事は、ZonengZoneが何であるかを理解するのに役立ちます。

https://blog.thoughtram.io/angular/2016/02/01/zones-in-angular-2.html

1
micronyks