.NET8 Blazor 从入门到精通:(二)组件
Blazor 组件
基础
新建一个项目命名为 MyComponents ,项目模板的交互类型选 Auto ,其它保持默认选项:

客户端组件 (Auto/WebAssembly):
最终解决方案里面会有两个项目:服务器端项目、客户端项目,组件按存放项目的不同可以分为以下两种组件:
服务器端组件:
- 主要用于服务器端渲染(SSR)
- 被放置在服务器端项目中
- 适用于不需要实时交互或复杂用户交互的场景
客户端组件 (Auto/WebAssembly):
- 组件位于客户端项目内
- 使用 WebAssembly 技术进行编译,能够直接与浏览器交互
- 适合需要交互性和实时更新的应用场景
- 使用 SignalR 可以实现实时通信,从而增强组件的功能性
两种组件选择原则如下:
- 如果组件不需要交互性,将其作为服务器端渲染的组件。
- 如果组件需要交互性(例如响应用户的输入、实时数据更新等),则应该考虑将其作为客户端组件,可以利用 SignalR 提供的实时通信功能。
在客户端项目中新建一个 Demo 组件:
<!-- 选择 Auto 或 WebAssembly ,否则无法交互 -->
@rendermode InteractiveAuto
<h3>Demo</h3>
<!-- 文本不为空时才显示标签 -->
@if (textInfo is not null)
{
<h4>Info: @textInfo</h4>
}
<!-- 按钮样式参考 Counter 组件 -->
<button class="btn btn-primary" @onclick="UpdateText">Update Text</button>
<!-- 委托方式调用方法,可以传入参数 -->
<button class="btn btn-primary" @onclick="(()=>{UpdateNumber(10);})">Update Number</button>
@code {
private string? textInfo = null;
private void UpdateText()
{
textInfo = "This is the new information";
}
private void UpdateNumber(int i = 0)
{
textInfo = $"This is number {i}";
}
}
在服务器端项目中的 Home 页面中引用 Demo 组件:
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<Demo />
在 _Imports.razor 中引用 Demo 组件的命名空间:
@using MyComponents.Client.Pages
路由
在客户端项目中添加一个 Start 组件,razor 代码如下:
@*组件可以同时有多个路由*@
@page "/page"
@page "/pages/start"
@*可以使用组件名作路由*@
@attribute [Route(nameof(Start))]
@*页面跳转必须指定交互性,并注入导航管理器*@
@rendermode InteractiveAuto
@inject NavigationManager Navigation
<h3>Start</h3>
@*通过NavigationManager.NavigateTo方法跳转到Counter组件*@
<button class="btn btn-primary" onclick="@(()=>Navigation.NavigateTo(nameof(Counter)))">Go to Counter</button>
@*执行完整的页面重新加载*@
<button class="btn btn-primary" onclick="@(()=>Navigation.Refresh(true))">Refresh</button>
@code {
}
上面的代码演示了如何使用路由和导航管理器进行页面跳转,跳转到其它组件时会用到增强导航,参考 增强的导航和表单处理 。
参数
组件参数
在客户端项目中添加一个 BetterCounter 组件,razor 代码如下:
@rendermode InteractiveAuto
<h3>BetterCounter</h3>
<p role="status">Current count: @CurrentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
//将目标成员表示为组件参数
[Parameter]
public int CurrentCount { get; set; }
private void IncrementCount()
{
CurrentCount++;
}
}
组件参数将数据传递给组件,使用组件类中包含 [Parameter] 特性的公共 C# 属性进行定义,参考组件参数 和 单向绑定 。
使用组件时需要将目标成员作为组件参数传递给组件,如在 Home 页面中引用 BetterCounter 组件:
<BetterCounter CurrentCount="100" />
<!-- 或 -->
<BetterCounter CurrentCount=@currentCount />
路由参数
路由器使用路由参数以相同的名称填充相应的组件参数,路由参数名不区分大小写,参考文档 路由参数 。
在 BetterCounter 组件的 razor 代码中添加如下路由:
@*路由参数(无约束)*@
@page "/BetterCounter/{CurrentCount}"
@*路由参数约束*@
@page "/BetterCounter/{CurrentCount:int}"
@*可选路由参数(与上面任意一个路由搭配使用实现可选效果)*@
@page "/BetterCounter"
为了实现可选路由参数,需要在组件中添加一个默认值:
//将目标成员表示为组件参数
//需要将参数属性的类型更改为可为 null,这样就可以分辨出它是否被指定了值
[Parameter]
public int? CurrentCount { get; set; }
//为可选参数指定默认值
protected override void OnInitialized()
{
base.OnInitialized();
CurrentCount = CurrentCount ?? 1;
}
添加一个 Titlet 成员来接受查询字符串的参数:
//指定组件参数来自查询字符串
//路由:/BetterCounter?Titlet=asd
[SupplyParameterFromQuery]
public string? Titlet { get; set; } = "BetterCounter";
路由参数:在添加组件的 @page 声明时,通过将路由参数的名称括在一对 { 大括号 } 中,在URL中定义了路由参数,参考示例 路由参数 。
路由参数约束:以冒号为后缀,然后是约束类型,约束类型参考文档 路由约束。
以路由 /BetterCounter/abs 为例:- 没有路由约束时会报类型转换异常(字符串无法转为int类型)
- 有路由约束时会显示404错误(没有匹配到该 URL)
可选路由参数:Blazor不明确支持可选路由参数,但通过在组件上添加多个 @page 声明,可以轻松实现等效的路由参数,参考文章 可选路由参数。
查询字符串:使用 [SupplyParameterFromQuery] 属性指定组件参数来自查询字符串,更多应用场景参考文档 查询字符串。
生命周期事件
以下简化图展示了 Razor 组件生命周期事件处理,参考文档 生命周期事件:

在 Counter 组件中添加日志记录,观察组件的生命周期:
@inject ILogger<Counter> log
//...
@code {
//...
protected override void OnInitialized()
{
log.LogInformation($"Initialized at {DateTime.Now}");
}
protected override void OnParametersSet()
{
log.LogInformation($"ParametersSet at {DateTime.Now}");
}
protected override void OnAfterRender(bool firstRender)
{
log.LogInformation("OnAfterRender: firstRender = {FirstRender}", firstRender);
}
}
组件初始化 (OnInitialized{Async}) :专门用于在组件实例的整个生命周期内初始化组件,参数值和参数值更改不应影响在这些方法中执行的初始化。
设置参数之后 (OnParametersSet{Async}):在 OnInitialized 或 OnInitializedAsync 中初始化组件后或父组件重新呈现并变更参数时调用。
组件呈现之后 (OnAfterRender{Async}):OnAfterRender 和 OnAfterRenderAsync 组件以交互方式呈现,并在 UI 已完成更新(例如,元素添加到浏览器 DOM 之后)后调用。OnAfterRender 和 OnAfterRenderAsync 的 firstRender 参数:
- 在第一次呈现组件实例时设置为 true。
- 可用于确保初始化操作仅执行一次。
运行后导航到Counter界面,控制台输出如下:

状态更改
StateHasChanged 通知组件其状态已更改。 如果适用,调用 StateHasChanged 会导致组件重新呈现。
将自动为 EventCallback 方法调用 StateHasChanged,也可以根据实际需求在组件中手动调用 StateHasChanged:
private async void IncrementCount()
{
currentCount++;
await Task.Delay(1000);
StateHasChanged();
currentCount++;
await Task.Delay(1000);
StateHasChanged();
currentCount++;
await Task.Delay(1000);
StateHasChanged();
}
如果不调用 StateHasChanged 则点击后只会第一个值和最后一个值显示 1 ,用 StateHasChanged 后则会依次显示 1 2 3 。
组件事件
嵌套组件的常见方案是在发生子组件事件时在父组件中执行某个方法(如子组件中的 onclick 事件),跨组件公开事件请使用 EventCallback ,父组件可向子组件的 EventCallback 分配回调方法。
在 Counter 组件中添加一个事件:
@code {
private int currentCount = 0;
//定义一个事件回调参数
[Parameter]
public EventCallback<int> OnCounterChange { get; set; }
private async Task IncrementCount()
{
currentCount++;
//触发事件回调
await OnCounterChange.InvokeAsync(currentCount);
}
}
在另一个客户端组件为 Counter 组件的事件分配回调方法(服务端组件会报错):
<Counter OnCounterChange="UpdateCounter" />
@code {
private int currentCount = 0;
private void UpdateCounter(int val)
{
currentCount = val;
}
}
.NET8 Blazor 从入门到精通:(二)组件的更多相关文章
- iOS开发-UI 从入门到精通(二)
iOS开发-UI 从入门到精通(二)是对 iOS开发-UI 从入门到精通(一)知识点的巩固,主要以习题练习为主,增强实战经验,为以后做开发打下坚实的基础! ※开发环境和注意事项: 1.前期iOS-UI ...
- Python基本语法,python入门到精通[二]
在上一篇博客Windows搭建python开发环境,python入门到精通[一]我们已经在自己的windows电脑上搭建好了python的开发环境,这篇博客呢我就开始学习一下Python的基本语法.现 ...
- PHP从入门到精通(二)
PHP从入门到精通 之PHP中的函数 各位开发者朋友大家好,自上次更新PHP的相关知识,得到了大家的广泛支持.PHP的火爆程度不言而喻,函数作为PHP中极为重要的部分,应诸位的支持,博主继续跟进更新 ...
- MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select
最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. 明确需求 书中提到的需求是一个基 ...
- SpringBoot从入门到精通二(SpringBoot整合myBatis的两种方式)
前言 通过上一章的学习,我们已经对SpringBoot有简单的入门,接下来我们深入学习一下SpringBoot,我们知道任何一个网站的数据大多数都是动态的,也就是说数据是从数据库提取出来的,而非静态数 ...
- python入门到精通[二]:基础学习(1)
摘要:Python基础学习: 注释.字符串操作.用户交互.流程控制.导入模块.文件操作.目录操作. 上一节讲了分别在windows下和linux下的环境配置,这节以linux为例学习基本语法.代码部分 ...
- MyBatis 入门到精通(二) SQL语句映射XML文件
MyBatis 真正强大之处就在这些映射语句,也就是它的魔力所在.对于它的强大功能,SQL 映射文件的配置却非常简单. 如果您比较SQL 映射文件配置与JDBC 代码,您很快可以发现,使用SQL 映射 ...
- Atom编辑器入门到精通(二) 插件的安装和管理
在本节中我们会学习如果安装和使用插件插件是Atom中一个非常重要的组成部分,很多功能都是以插件形式存在的.比如上篇文章中提到的目录树和设置等窗口都是通过默认安装的插件来实现的. 查看已安装的插件 打开 ...
- vue 从入门到精通(二)
上一篇总结了一些vue的理论知识,如果你没看懂的话--那返回去继续去看啊!反正我要开始第二篇了. vue提供了大量的指令,比如:v-if,v-bind,v-on--太多,多写项目,多看API,这里就不 ...
- flutter从入门到精通二
静态方法和静态属性(static): 通过static修饰的方法和属性称为静态方法和静态属性,注意静态方法和静态属性只能通过类名访问,不能通过对象访问. 静态方法不能访问非静态的属性和非静态方法,反正 ...
随机推荐
- CSS和CSS3(背景,图片,浮动等)
CSS和CSS3背景图片 CSS的背景,无法伸缩图片. <!DOCTYPE html> <html lang="en"> <head> < ...
- SDL3 入门(4):选择图形引擎
SDL2 创建渲染器时只能指定使用软件渲染还是硬件加速,无法选择使用哪种图形引擎实现硬件加速.SDL3 对此做了优化,可以在创建渲染器时指定 rendering driver 也就是图形引擎,比如在 ...
- 嵌入式测试手册——基于NXP iMX6ULL开发板(2)
基于测试板卡:创龙科技TLIMX6U-EVM是一款基于NXP i.MX 6ULL的ARM Cortex-A7高性能低功耗处理器设计的评估板,由核心板和评估底板组成.核心板经过专业的PCB Layout ...
- 在Mac上使用Emacs初步
其他操作系统估计也差不多. 安装 如果使用brew就是brew install emacs.安装后不会在Applications里面显示一个程序,需要在命令行里执行emacs. 使用 进入和退出 上面 ...
- python3 pip3 安装 xmlrpc 失败
python2 使用的是xmlrpclib库,到了 python3, 就直接使用 xmlrpc.client 和 xmlrpc.server了. 接下来,我使用 pip3 install xmlrpc ...
- SpringCloud 微服务与微服务对接心德
导读 先简单介绍下背景,公司里的项目,有一块需要与公司里的其他项目组对接.我们这边用的注册中心Nacos,对方用的eureka,之前都是自己写接口,然后服务中引入这个接口工程,都是注册到同一个注册中心 ...
- 2022 开源之夏 | Curve 邀你与中国存储软件共成长,赢万元奖金
Curve 社区携手开源之夏,邀你开展有趣而精彩的开源之旅,直面社区大咖,积累项目经历,摘取丰厚奖金,共同推进我国基础软件自主创新 2022 年,Curve 社区再次加入系列高校开源活动 -- 开源之 ...
- 重磅集结!CNCF/VMware/PingCAP/网易数帆/阿里云联合出品云原生生态大会
"云原生(Cloud Native)"这个词在2020年刷屏了.在企业积极进行数字化转型,全面提升效率的今天,云原生被认为是云计算的"下一个时代". 12月16 ...
- K8S 中的 CRI、OCI、CRI shim、containerd
哈喽大家好,我是咸鱼. 好久没发文了,最近这段时间都在学 K8S.不知道大家是不是和咸鱼一样,刚开始学 K8S.Docker 的时候,往往被 CRI.OCI.CRI shim.containerd 这 ...
- Swift开发基础03-函数
定义 形参默认是let,也只能是let func sum(v1: Int, v2: Int) -> Int { return v1 + v2 } sum(v1: 10, v2: 20) // 无 ...