.NET8 Blazor 从入门到精通:(二)组件

张裕  金牌会员 | 2024-8-16 18:39:26 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 566|帖子 566|积分 1698

目录

Blazor 组件

基础

新建一个项目命名为 MyComponents ,项目模板的交互类型选 Auto ,其它保持默认选项:

客户端组件 (Auto/WebAssembly):
最终解决方案里面会有两个项目:服务器端项目客户端项目,组件按存放项目的不同可以分为以下两种组件:

  • 服务器端组件:

    • 主要用于服务器端渲染(SSR)
    • 被放置在服务器端项目中
    • 适用于不需要实时交互或复杂用户交互的场景

  • 客户端组件 (Auto/WebAssembly):

    • 组件位于客户端项目内
    • 利用 WebAssembly 技能举行编译,可以或许直接与欣赏器交互
    • 得当需要交互性和实时更新的应用场景
    • 利用 SignalR 可以实现实时通讯,从而加强组件的功能性

两种组件选择原则如下:

  • 如果组件不需要交互性,将其作为服务器端渲染的组件。
  • 如果组件需要交互性(比方响应用户的输入、实时数据更新等),则应该思量将其作为客户端组件,可以利用 SignalR 提供的实时通讯功能。
在客户端项目中新建一个 Demo 组件:
  1. @rendermode InteractiveAuto
  2. <h3>Demo</h3>
  3. @if (textInfo is not null)
  4. {
  5.     <h4>Info: @textInfo</h4>
  6. }
  7. <button  @onclick="UpdateText">Update Text</button>
  8. <button  @onclick="(()=>{UpdateNumber(10);})">Update Number</button>
  9. @code {
  10.     private string? textInfo = null;
  11.     private void UpdateText()
  12.     {
  13.         textInfo = "This is the new information";
  14.     }
  15.     private void UpdateNumber(int i = 0)
  16.     {
  17.         textInfo = $"This is number {i}";
  18.     }
  19. }
复制代码
在服务器端项目中的 Home 页面中引用 Demo 组件:
  1. @page "/"
  2. <PageTitle>Home</PageTitle>
  3. <h1>Hello, world!</h1>
  4. Welcome to your new app.
  5. <Demo />
复制代码
在 _Imports.razor 中引用 Demo 组件的命名空间:
  1. @using MyComponents.Client.Pages
复制代码
路由导航

在客户端项目中添加一个 Start 组件,razor 代码如下:
  1. @*组件可以同时有多个路由*@
  2. @page "/page"
  3. @page "/pages/start"
  4. @*可以使用组件名作路由*@
  5. @attribute [Route(nameof(Start))]
  6. @*页面跳转必须指定交互性,并注入导航管理器*@
  7. @rendermode InteractiveAuto
  8. @inject NavigationManager Navigation
  9. <h3>Start</h3>
  10. @*通过NavigationManager.NavigateTo方法跳转到Counter组件*@
  11. <button  onclick="@(()=>Navigation.NavigateTo(nameof(Counter)))">Go to Counter</button>
  12. @*执行完整的页面重新加载*@
  13. <button  onclick="@(()=>Navigation.Refresh(true))">Refresh</button>
  14. @code {
  15. }
复制代码
上面的代码演示了如何利用路由和导航管理器举行页面跳转,组件可以同时有多个路由,也可以利用组件名作路由
跳转到其它组件时会用到加强导航,参考 加强的导航和表单处置惩罚
参数

组件参数

在客户端项目中添加一个 BetterCounter 组件,razor 代码如下:
  1. @rendermode InteractiveAuto
  2. <h3>BetterCounter</h3>
  3. <p role="status">Current count: @CurrentCount</p>
  4. <button  @onclick="IncrementCount">Click me</button>
  5. @code {
  6.     //将目标成员表示为组件参数
  7.     [Parameter]
  8.     public int CurrentCount { get; set; }
  9.     private void IncrementCount()
  10.     {
  11.         CurrentCount++;
  12.     }
  13. }
复制代码
组件参数将数据传递给组件,利用组件类中包罗 [Parameter] 特性的公共 C# 属性举行定义,参考组件参数单向绑定
利用组件时需要将目标成员作为组件参数传递给组件,如在 Home 页面中引用 BetterCounter 组件:
  1. [/code][size=4]路由参数[/size]
  2. 路由器利用路由参数[b]以相同的名称添补相应的组件参数,路由参数名不区分巨细写[/b],参考文档 [url=https://learn.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-8.0#route-parameters]路由参数[/url] 。
  3. 在 BetterCounter 组件的 razor 代码中添加如下路由:
  4. [code]@*路由参数(无约束)*@
  5. @page "/BetterCounter/{CurrentCount}"
  6. @*路由参数约束*@
  7. @page "/BetterCounter/{CurrentCount:int}"
  8. @*可选路由参数(与上面任意一个路由搭配使用实现可选效果)*@
  9. @page "/BetterCounter"
复制代码
为了实现可选路由参数,需要在组件中添加一个默认值:
  1. //将目标成员表示为组件参数
  2. //需要将参数属性的类型更改为可为 null,这样就可以分辨出它是否被指定了值
  3. [Parameter]
  4. public int? CurrentCount { get; set; }
  5. //为可选参数指定默认值   
  6. protected override void OnInitialized()
  7. {
  8.     base.OnInitialized();   
  9.     CurrentCount = CurrentCount ?? 1;
  10. }
复制代码
添加一个 Titlet 成员来担当查询字符串的参数:
  1. //指定组件参数来自查询字符串
  2. //路由:/BetterCounter?Titlet=asd
  3. [SupplyParameterFromQuery]
  4. public string? Titlet { get; set; } = "BetterCounter";
复制代码

  • 路由参数:在添加组件的 @page 声明时,通过将路由参数的名称括在一对 { 大括号 } 中,在URL中定义了路由参数,参考示例 路由参数
  • 路由参数束缚:以冒号为后缀,然后是束缚类型,束缚类型参考文档 路由束缚。以路由 /BetterCounter/abs 为例:

    • 没有路由束缚时会报类型转换异常(字符串无法转为int类型)
    • 有路由束缚时会显示404错误(没有匹配到该 URL)

  • 可选路由参数:Blazor不明确支持可选路由参数,但通过在组件上添加多个 @page 声明,可以轻松实现等效的路由参数,参考文章 可选路由参数
  • 查询字符串:利用 [SupplyParameterFromQuery] 属性指定组件参数来自查询字符串,更多应用场景参考文档 查询字符串
生命周期事件

以下简化图展示了 Razor 组件生命周期事件处置惩罚,参考文档 生命周期事件

在 Counter 组件中添加日志记录,观察组件的生命周期:
  1. @inject ILogger<Counter> log
  2. //...
  3. @code {
  4.     //...
  5.     protected override void OnInitialized()
  6.     {
  7.         log.LogInformation($"Initialized at {DateTime.Now}");
  8.     }
  9.     protected override void OnParametersSet()
  10.     {
  11.         log.LogInformation($"ParametersSet at {DateTime.Now}");
  12.     }
  13.     protected override void OnAfterRender(bool firstRender)
  14.     {
  15.         log.LogInformation("OnAfterRender: firstRender = {FirstRender}", firstRender);
  16.     }
  17. }
复制代码

  • 组件初始化 (OnInitialized{Async}) :专门用于在组件实例的整个生命周期内初始化组件,参数值和参数值更改不应影响在这些方法中实行的初始化。
  • 设置参数之后 (OnParametersSet{Async}):在 OnInitialized 或 OnInitializedAsync 中初始化组件后或父组件重新出现并变更参数时调用。
  • 组件出现之后 (OnAfterRender{Async}):OnAfterRender 和 OnAfterRenderAsync 组件以交互方式出现,并在 UI 已完成更新(比方,元素添加到欣赏器 DOM 之后)后调用。OnAfterRender 和 OnAfterRenderAsync 的 firstRender 参数:

    • 在第一次出现组件实例时设置为 true。
    • 可用于确保初始化操作仅实行一次。

运行后导航到Counter界面,控制台输出如下:

状态更改

StateHasChanged 通知组件其状态已更改。 如果适用,调用 StateHasChanged 会导致组件重新出现
将自动为 EventCallback 方法调用 StateHasChanged,也可以根据实际需求在组件中手动调用 StateHasChanged:
  1. private async void IncrementCount()
  2. {
  3.     currentCount++;
  4.     await Task.Delay(1000);
  5.     StateHasChanged();
  6.     currentCount++;
  7.     await Task.Delay(1000);
  8.     StateHasChanged();
  9.     currentCount++;
  10.     await Task.Delay(1000);
  11.     StateHasChanged();
  12. }
复制代码
上面的代码,如果不调用 StateHasChanged 则点击后只会显示 1 ,用 StateHasChanged 后则会依次显示 1 2 3 。
组件事件

嵌套组件的常见方案是在发生子组件事件时在父组件中实行某个方法(如子组件中的 onclick 事件),跨组件公开事件请利用 EventCallback ,父组件可向子组件的 EventCallback 分配回调方法。
在 Counter 组件中添加一个事件:
  1. @code {
  2.     private int currentCount = 0;
  3.     //定义一个事件回调参数
  4.     [Parameter]
  5.     public EventCallback<int> OnCounterChange { get; set; }
  6.     private async Task IncrementCount()
  7.     {
  8.         currentCount++;
  9.         //触发事件回调
  10.         await OnCounterChange.InvokeAsync(currentCount);
  11.     }
  12. }
复制代码
在另一个客户端组件为 Counter 组件的事件分配回调方法(服务端组件会报错):
  1. <Counter OnCounterChange="UpdateCounter" />
  2. @code {
  3.     private int currentCount = 0;
  4.     private void UpdateCounter(int val)
  5.     {
  6.         currentCount = val;
  7.     }
  8. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张裕

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表