17.模版化组件

在组件中放置一个可渲染的代码片段供外部调用者来传入要渲染的内容及渲染样式,这样的组件就叫做模版化的组件。一般是一个支持泛型的组件,目标为消费者封装重复使用的通用性良好的UI组件。比如一个用来给用户呈现表格数据的表格组件。

示例组件 GenaricTable.razor 代码如下:

@typeparam TData

@if(Data is not null)
{
    <table class="table">
        <thead>
            <tr>
                @HeaderTemplate
            </tr>
        </thead>
        <tbody>
            @foreach(var item in Data)
            {
                <tr>
                    @RowTemplate?.Invoke(item);
                </tr>
            }
        <tbody>
    </table>
}

@code
{
    [parameter]public IEnumerable<TData>?  Data{get;set;}
    [parameter]public RenderFragment<TData>? RowTemplate{get;set;}
    [parameter]public RenderFragment? HeaderTemplate{get;set;}
}

消费者代码如下:

@Page "/genaric-table"

<GenaricTable Data="Users">
    <RowTemplate>
        <td>@context.Id</td>
        <td>@context.Name</td>
    </RowTemplate>
</GenaricTalbe>

@{
    class user
    {
        public int Id{get;set;}
        public string? Name{get;set;}
    }
    IEnumerable<User> Users => new List<User>
    {
        new(){Id=1,Name="张三"},
        new(){Id=2,Name="李四"}
    }
}
  • 说明:
    RenderFragment 或 RenderFragment 可渲染片段,实际就是委托
    如果是泛型可渲染片段如 RenderFragment<TData>? RowTemplate{get;set;} 则在调用时,Blazor会为调用者使用的地方自动引入一个叫 @context 的数据上下文变量,它即是该泛型委托的封闭类型的一个约定实例。

18.渲染模式或叫呈现模式或叫交互模式

1.交互模式的设计思想

1.1.Blazor Server(InteractiveServer)

属于SSR(Server Side Render),通过 SignalR 由服务器端运行Blazor的C#代码,这些C#代码的主要职责就是随着SignalR传递元素事件或js事件到服务器端,然后由服务器端依据事件执行改动Dom元素的动作,最后把改动后的html代码传递给前端的浏览器去呈现。
Blzaor Server传输的数据比较小,仅需要传输160KB左右的数据,页面几乎瞬时加载完成。因为Blazor Server项目不涉及WebAssembly,所有组件呈现逻辑都是在服务端实现的,只是将需要处理的UI更新通过SignalR发送给浏览器。
image
浏览器仅需处理javascript、CSS和HTML代码。但这样导致Blazor Server项目必须实时和服务端交互,使用类似_blazor?id=xxx这样的URL路径连接并传递数据:

1.2.Blazor WebAssembly(InteractiveWebAssembly)

Blazor WebAssembly依赖于WASM标准,WebAssembly是一种可移植的二进制代码语言,现代浏览器都支持WASM。
image
Blazor WebAssembly传输的数据比较大,运行Blazor WebAssembly项目时,所有dll都必须传输到客户端。故程序直接在浏览器中执行,即使断网也不受影响。WebAssembly不依赖.NET运行时,从而可部署在静态文件服务器上。

1.3.InteractiveAuto

使用该模式时,先采用InteracitveServer,等C#程序集下载到浏览器完毕后自动切换为InteractiveWebAssembly交互模式。

2.代码中启用对交互式呈现模式的支持(Blazor Web 应用项目模板)

2.1 配置asp.net项目的服务和中间件

  • 组件生成器扩展:
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents()
    .AddInteractiveWebAssemblyComponents();

通过调用 AddRazorComponents 添加 Razor 组件的服务。
AddInteractiveServerComponents 添加服务以支持呈现交互式服务器组件。
AddInteractiveWebAssemblyComponents 添加服务以支持呈现交互式 WebAssembly 组件。

  • 终结点约定生成器扩展:
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .AddInteractiveWebAssemblyRenderMode();

AddInteractiveServerRenderMode 为应用配置交互式服务器端呈现(交互式 SSR)。
AddInteractiveWebAssemblyRenderMode 为应用配置交互式 WebAssembly 呈现模式。

  • 在根组件App.razor中的设置
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="BlazorApp.styles.css" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet @rendermode="@InteractiveAuto" />
<head>
<body>
    <Routes @rendermode="@InteractiveAuto" />
    <script src="_framework/blazor.web.js" />
</body>
</html>
  • 说明
    如果在创建项目时,在项目模版中的选项交互性区域(Interactivity location)选择Per page/component,则上面代码中不会出现对渲染模式指定的代码:@rendermode="@InteractiveAuto"

2.2 将呈现模式应用于组件实例或组件定义

实例:<Dialog @rendermode="InteractiveServer" />
其中 @rendermode 指令来源于Components/_Imports.razor文的的一个静态using指令:@using static Microsoft.AspNetCore.Components.Web.RenderMode
定义:

@page "/..."
@rendermode InteractiveServer

2.3 以WebAssembly和Auto模式创建的解决方案的两个项目的说明

假设xxx和xxx.Client
xxx:就是InteraciveServer项目
xxx.Client:是InteractiveWebAssembly项目
如果创建的组件或页面交互模式是auto或webassembly时,需要把它们放在.Client项目中
Server端可以兼容调用WebAssembly端,反之不行。

2.4 禁止设置包含有RenderFrament<>类型参数的组件的交互模式

原因是因为RenderFrament本身是不可序列化的委托类型。解决方法是再创建一个无RenderFrament<>类型参数的外层组件,把这种组件包含在其中即可。

3.呈现模式的传播、继承

呈现模式会向下传播组件层次结构。
应用呈现模式的规则:
3.1 默认呈现模式为静态(即不会有交互生效,比如对按钮事件的响应)。
3.2 交互式服务器 (InteractiveServer)、交互式 WebAssembly (InteractiveWebAssembly) 和交互式自动 (InteractiveAuto) 呈现模式可从组件使用,包括对同级组件使用不同的呈现模式。
3.3 无法在子组件中切换到其他交互式呈现模式。 例如,服务器组件不能是 WebAssembly 组件的子组件。
3.4 从静态父级传递到交互式子组件的参数必须是 JSON 可序列化的。 这意味着无法将呈现片段或子内容从静态父级组件传递到交互式子组件。
3.5 如果将有交互式的组件放置在静态呈现的父级组件中,则交互组件也会以静态方式呈现。
3.6 Server模式的页面可包含WebAssembly组件,反之不行。

提醒:

  1. 做一个组件时,最好别指定交互模式,而是交给调用的页面去指定。
posted on 2024-03-26 20:41  hrx521  阅读(19)  评论(0编辑  收藏  举报