一、基本理解
首次接触“生命周期”这个名词,是比较晦涩的,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("组件销毁"); } }