22. NET8中的预呈现
- 预呈现是在服务器上初始呈现页面内容的过程(无需为呈现的控件启用事件处理程序)。服务器会根据初始请求尽快输出页面的HTML UI,这会让用户感觉应用提高了响应速度。预呈现还可以通过呈现搜索引擎用于计算网页排名的初始HTTP响应的内容,来改进搜索引擎优化(SEO)
https://learn.microsoft.com/zh-cn/aspnet/core/blazor/components/prerender?view=aspnetcore-8.0
没有预呈现效果就是,当页面初始化方法中要执行一些耗时任务时,整个页面的渲染必须等待这些耗时任务执行完毕,然后才能呈现。尤其在WebAssembly项目中,前面要下载整个程序集...
预呈现试图过把耗时任务先暂时剥离,而尝试先呈现能够渲染的最初始的页面Html和CSS,比如先呈现页面框架,从而减少用户等待...
22.1 代码中开启预呈现的方法
从组件参数设置交互模式时,如代码:
<Perrender Title="开启预呈现" @rendermode="new InteractiveServerRenderMode(true)">
<Perrender Title="开启预呈现" @rendermode="new InteractiveWebAssemblyRenderMode(true)">
22.2 预呈现带来的负面问题
- 22.2.1 在InteractiveServerRenderMode中,写在生命周期OnInitializedAsync()方法中的耗时任务,会在任务完成后,又渲染一次页面。
- 22.2.2 两次渲染页面,会让第一次的页面中的元素值或都说某些状态被第二次渲染而覆盖,造成状态无法保持(比如第一次渲染产生了从随机函数获得了一个随机数,第二次渲染又会获得一次而且与第一次不同)。解决方法:Blazor为组件专们设计了一个用来进行状态持久化的类型 PersistentComponetState 它相当于一个单例的字典类型或者一种缓存,使用时在第一次渲染时,把第一次渲染产生的状态保存在此,当第二次渲染时从此中取出即可。如代码:
@page "/prerendered-counter-2"
@implements IDisposable
@inject ILogger<PrerenderedCounter2> Logger
@inject PersistentComponentState ApplicationState
<PageTitle>Prerendered Counter 2</PageTitle>
<h1>Prerendered Counter 2</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
private PersistingComponentStateSubscription persistingSubscription;
protected override void OnInitialized()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistCount);
if (!ApplicationState.TryTakeFromJson<int>(
nameof(currentCount), out var restoredCount))
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
else
{
currentCount = restoredCount!;
Logger.LogInformation("currentCount restored to {Count}", currentCount);
}
}
private Task PersistCount()
{
ApplicationState.PersistAsJson(nameof(currentCount), currentCount);
return Task.CompletedTask;
}
void IDisposable.Dispose() => persistingSubscription.Dispose();
private void IncrementCount()
{
currentCount++;
}
}
- 22.2.3 如果渲染模式是在组件定义时指定的,则无法在组件使用时使用预呈现。
24.渲染树
blazor的组件就是一个类。我们也来尝试用C#类创建组件。
- 1.把类继承自ComponentBase
- 2.重写基类BuildRenderTree(RenderTreeBuilder builder)方法,从该方法中控件一切
- 3.使用
builder.OpenElement(0,"button");
和builder.CloseElement();
成对同时出现的方式创建一个html元素,其中第一个参数是该元素在整个组件中的索引键编码(用常量不要用变量),元素之间不可重复,第二个参数是指定html元素的类型 - 4.使用参数型属性 RenderFragment? ChildContent 和
builder.AddContent(10,ChildContent);
来动态创建外部传进来的可渲染片断 - 5.使用
builder.AddAttribute(1,"class","btn btn-success");
创建html元素属性;使用builder.AddAttribute(1,"onclick",()=>{});
创建元素事件。
namespace BlazorApp.Client.Components;
public class Button : ComponentBase
{
[Parameter] public RenderFragment? ChildContent{get;set;}
[Parameter] public bool Outline{get;set;}
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0,"button");
//增加一个html元素属性
//builder.AddAttribute(1,"class","btn btn-success");
builder.AddAttribute(1,"class",$"btn btn-{(Outline?"outline-":"")}success");//以参数控制样式
builder.AddContent(10,ChildContent);
builder.CloseElement();
}
}