一、基本理解
首次接觸“生命週期”這個名詞,是比較晦澀的,Vue中又有生命週期鉤子,而Blazor則是虛方法重寫,容易蒙。所以,我嘗試從初學者的角度來闡述一下。
1、我們在基礎部分已經知道,元件有兩部分組成,一是邏輯層,有資料和方法(方法本質上也是資料);二是檢視層,雖然有自定義元件,但拆到底,還是HTML原生標籤。
2、元件的初次呈現,可以先簡單的理解為兩個過程,第一步,完成邏輯層的例項化,類似於一個類的例項化,為檢視層準備資料;第二步,完成檢視層DOM的渲染,會使用到邏輯層的資料。這就是生命週期,當然中間過程我們需要繼續細化。
3、在這個生命週期中,我們肯定想做兩件事情,一是當到達特定階段時,讓我知道,這樣我可以執行某些任務;二是我還能根據一些情況的判斷,來決定生命週期是否繼續執行。
4、為了實現上面的兩件事情,Vue為我們準備了不同階段的生命週期鉤子,Blazor則是虛方法。兩者的原理是一樣的,本質上,是一種命名約定和方法重寫。如在完成檢視層的DOM渲染後,Vue執行一個名字叫onMounted()的方法,Blazor則執行一個名字叫OnAfterRender()的方法。Vue中,我們使用回撥,Blazor中我們通過重寫override,就能實現自己想執行的邏輯。
5、Blazor生命週期的使用,更加接近於本質,虛方法和方法重寫,有C#基礎的,都好理解,而Vue的鉤子,雖然易用,但要想整通透了,則更加晦澀一些。如果看Blazor生命週期的原始碼,裡面有很多類似這樣的程式碼:if(某某狀態出現){則呼叫某個方法},條件就是用來判斷生命週期到哪個階段了,方法體中呼叫的方法就是Blazor的生命週期虛方法,是不是很容易理解?!
二、基本使用
兩者的語法使用都非常簡單,直接在邏輯層,按約定寫方法就可以。但要使用得當且靈活運用,還是需要了解每一個生命週期過程的細節,尤其是Blazor,會相對複雜一些。Blazor提供了更加豐富的控制方法,但也提高了使用的複雜度,看產品路線圖,未來還會繼續增加生命函式。對生命週期細節更深入的學習,我們放到第二節,這節先簡單瞭解一下
1、 Vue的生命週期鉤子,作為API匯入,方法體中寫回撥邏輯。
//Vue======================================= onBeforeMount(()=>{console.log("元件渲染/掛載前")}) onMounted(()=>{console.log('元件渲染/掛載後')}) onBeforeUpdate(()=>{console.log('資料更新前')}) onUpdated(()=>{console.log('資料更新後')}) onBeforeUnmount(()=>{console.log('元件銷燬前')}) onUnmounted(()=>{console.log('元件銷燬後')})
2、Blazor直接重寫生命週期函式(方法簽名一致),方法體中寫自己的邏輯,部分虛擬函式提供了入參
//Blazor==================================== public override async Task SetParametersAsync(ParameterView parameters) { Console.WriteLine("引數設定前"); await base.SetParametersAsync(parameters); //完成內部欄位/屬性的初始化,收集外部傳引數到ParameterView,未給引數屬性賦值 //最後執行【base.SetParametersAsync】,給引數屬性賦值 } protected override void OnInitialized() { Console.WriteLine("組建初始化"); //建立元件例項,完成元件的初始化,此時引數屬性已被賦值 //有一個配對的非同步函式OnInitializedAsync } protected override void OnParametersSet() { Console.WriteLine("引數設定後"); //這個生命函式更像是OnInitialized的備胎 //OnInitialized只在元件初始化時執行一次,引數更新時,並不執行 //所以需要一個生命函式來完成OnInitialized做的事情 //有一個配對的非同步函式OnParametersSetAsync } protected override void OnAfterRender(bool firstRender) { Console.WriteLine("元件渲染後"); //DOM完成渲染後,此時可以獲得最新的ref //是否渲染DOM,根據虛擬DOM的差量演算法 //可能引起渲染:父元件重新渲染、父元件傳入的引數屬性變化、本元件欄位/屬性變化、本元件事件執行等 //有一個配對的非同步函式OnAfterRenderAsync } //Dispose不屬於生命函式,所以用法比較特別,先實現IDisposable介面,然後呼叫介面的Dispose方法 //這個設計比較奇怪的,也沒有查到這麼設計的原因,推斷是防止重複執行,因為Dispose是框架層級的一個方法 @implements IDisposable @code { void IDisposable.Dispose() { Console.WriteLine("元件銷燬"); } }