2017-08-27 78 views

回答

6

NgZone是圍繞Zone.js的包裝是,爲了使他們可追蹤圍繞創建異步函數上下文庫。

Angular的變化檢測主要依賴於Zones,How?

當需要運行變更檢測時,角度需要一種不受影響的方式,它基本上只是更新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時間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函數,並且在更新模型後,我希望視圖被更新的任何地方調用它們,right(回到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()功能每一個onclick,因爲它支持到click甚至處理程序本身。

在Angular中,updateTextchange detection,Angular已經掛鉤了所有本地事件(通過使用區域)。

所以,當你寫:

setTimeout(()=>{ 
     console.log('Do something'); 

    },100); 

你實際上寫是一樣的東西:

setTimeout(()=>{ 
     console.log('Do something'); 
     runAngularsChangeDetection(); 
    },100); 

以上是遠是什麼在現實中發生的事情,但它的整體的心臟我們爲什麼需要它們/

更新:

我們什麼時候應該使用NgZone

會有很多的情況下,當你想使用NgZone,我可以說出兩種:

1 - 當你想要的東西角的變化檢測之外運行:

還記得我說過角有掛鉤在所有的異步事件? window.onScroll就是其中之一,現在可以說,我們想做一些當用戶滾動計算,你通常做的是:

window.onscroll =()=>{ 

    // do some heavy calculation : 
    }  

現在,滾動時,你函數被調用,通常你所期望的,但你可能會注意到你會遇到一些性能問題,這可能是因爲Angular在每一個滾動事件(預期行爲)上運行changeDetection

如果你的組件中有很多綁定,那麼你一定會注意到滾動時的性能下降。

所以一個方法是說,哎角,無視我的onscroll事件,我知道我在做什麼,我不想讓你運行變化檢測,在這種情況下,你會使用NgZone

constructor(private zone:NgZone){ 
    this.zone.runOutsideOfAngular(()=>{ 
     window.onscroll =()=>{ 
     // do some heavy calculation : 
     } 
    }) 
    } 

這將確保Angular不會在滾動時運行更改檢測。

另一種情況是與上面完全相反,你有一個函數在Angular的區域之外,你希望它在裏面,就像第三方庫爲你做一些東西,你想要它綁定到你的角度週期。

this.zone.run(()=>{ 
     $.get('someUrl').then(()=>{ 
      this.myViewVariable = "updated"; 
     }) 
    }); 

不使用區,你最有可能需要做的:

  $.get('someUrl').then(()=>{ 
      this.myViewVariable = "updated"; 
      this.changeDetectorRef.detectChanges(); 
     }) 

但是請注意,當你的功能區(run方法)中您不必手動調用detectChanges你自己和角會做這項工作

+0

感謝您對問題1和問題2的詳細解釋。什麼時候應該在角項目中使用ngZone。如果我們這樣做:從'@ angular/core'導入{NgZone};我們可以使用API​​,比如run,runOutsideAngular等,我想知道他們什麼時候應該在實踐中使用? –

+0

我會更新我的答案 – Milad

+0

這是否回答你的問題? – Milad