首发于:http://www.blazor.group:8000/topic/reply?tpid=9
开门见山,不介绍,不废话
建议食用本文前先食用 https://www.cnblogs.com/wzxinchen/p/12082136.html
Blazor 绑定(绑定就是刷新)机制有以下几种
StateHasChanged
强制重新绑定(重新绑定即刷新)对于第三点,注册事件是指类似于以下代码
<BMenu OnClick="ShowMenu"></BMenu>
注意这代码是瞎写的,仅仅为了示例
在上面代码中,注册了 OnClick 事件,处理程序为 ShowMenu
OnClick 既然是事件,那它总得有个方法签名,来规定 ShowMenu 的方法签名是什么
一般来说,有两种方法签名:
EventCallBack
结构体对于第一种情况,OnClick 事件的定义往往是
[Parameter]
public Action OnClick {get;set;}
对于第二种情况,OnClick 事件的定义往往是
[Parameter]
public EventCallBack OnClick {get;set;}
这两种情况在调用方注册的方法是一样的,那么这两种情况有什么不一样的?
不同点很小,第一种情况没有什么好说的,第二种情况,EventCallBack
内部调用了 StateHasChanged
。也就是说,如果事件定义是第二种,那么在方法执行完后会自动刷新一次,如果是第一种,则需要手动刷新
Blazor 的 ComponentBase 类中,提供了 ShouldRender 这个方法,当这个方法返回为 false 时,不会执行渲染,即使你调用了 StateHasChanged,仍然不会渲染,这相当于让你来决定,什么时候才是真的需要渲染,什么时候调用 StateHasChanged 才会生效。
基于 Blazor 的解决办法,当组件第一次渲染完成之后,ShouldRender 会返回为 false,然后后面调用都返回 false,对于任意一个组件,若出现没刷新的情况下,请考虑这个因素。
那么,如何让 Blazui 组件进行刷新呢?方法很简单,调用该组件的 MarkAsRequireRender 方法,标记该组件需要刷新。注意这个方法只是标记为需要刷新,如果不是自动调用的 StateHasChanged 方法,那么你需要手动调一次才刷新,这个方法 Blazui 封装为 Refresh 方法,内部直接调的 StateHasChanged 方法
到了这步,仍然没解决,可能会有些头疼
这里涉及到一个很重要的概念,Blazor 中,一个页面中的所有组件,是一颗树
可以简单理解为二叉树或是N叉树,每一个节点,就是一个组件,这个节点下的直属节点,是这个组件的子组件
<A>
<B>
<C>
</C>
</B>
</A>
A 是 B 的父组件,B 是 C 的父组件,要刷 C,你必须刷 B,注意这里的刷 B 并不会刷新 B 本身,而是刷的 B 的直属子组件,现在,你应该可以理解,我要刷新 B,我又该刷谁?当然是刷 B 的父组件
为什么会这样?因为你如果刷新 B,那么 B 所需要的参数根本不会更新,这样一来也根本无法刷新数据,它的主要目的,是更新 B 的直属子组件的所有参数,这样才能刷新 B 的直属子组件
Blazor 中,一切皆组件,当前页面它仍然是个组件,按照第一点讲到的,你大概可以理解这种情况该怎么办,很简单,设置当前页面为需要刷新即可
若当前页面没有继承 BComponentBase 这个类,则不需要考虑这个情况。
这种情况是比较坑的,不容易发现。
考虑下面的代码
public void Test(){
Task.Factory.StartNew(()=>{
//从数据库拉数据
});
}
Test 是 OnClick 事件的处理方法,很简单的一个情况,假设它不存在我们之前说的所有情况,这样写,仍然有概率不刷新,注意,是有概率,只是这概率特高。
当这个方法执行完并且开始执行 StateHasChanged 时,异步任务里面的拉取数据的代码执行完了吗?不一定,天知道。
通常情况是没执行完,那么就是说,当刷新时,数据压根就没拉到,这样的话,你的界面当然不会更新。
public async Task Test(){
await Task.Factory.StartNew(()=>{
//从数据库拉数据
});
}
改成这样即可
原文:https://www.cnblogs.com/wzxinchen/p/why-my-blazor-component-not-refresh.html