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();
	}
}
posted on 2024-03-31 18:31  hrx521  阅读(19)  评论(0编辑  收藏  举报