Blazor组件在ASP.NET Core中如何实现高效的前端开发?

2026-03-30 10:561阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3831个文字,预计阅读时间需要16分钟。

Blazor组件在ASP.NET Core中如何实现高效的前端开发?

目录+ 关于组件+ 组件类+ 静态资源+ 路由与路由参数+ 组件参数+ 创建会话写入组件参数+ 子内容+ 属性展开+ 任意参数+ 捕获组件引用+ 外部调用组件方法更新状态

目录
  • 关于组件
  • 组件类
  • 静态资产
  • 路由与路由参数
  • 组件参数
  • 请勿创建会写入其自己的组参数属性的组件
  • 子内容
  • 属性展开
  • 任意参数
  • 捕获对组件的引用
  • 在外部调用组件方法以更新状态
  • 使用 @ 键控制是否保留元素和组件
  • 指定基类
  • 指定属性
  • 导入组件
  • 原始 HTML

项目 Blazor 中,使用.razor结尾的文件,称为组件;而 Blazor 中的组件,正式名称是razor 组件;

Blazor 组件是 razor 过渡而来的,使用 razor 的基本语法特性,但是 Balzor 不支持 razor 中的标记帮助程序。

关于组件

.razor文件分为页面(带@page)和组件(不带@page,或者说页面组件和非页面组件。两者区别在于页面有路由,可以直接通过 URI 访问,一般放在 Page 文件夹中;而组件,作为一个部件,必须嵌入其它组件中,在页面中显示,一般放到 Shared 文件夹中,供多个页面共享、复用。
本文接下来所指的组件都是非页面组件。
.razor文件中,开头有@page标记的,就是页面组件,没有的就是非页面组件。
当然两者并没有严格的区分。
组件命名时,应该带上Component后缀。

组件类

每个.razor文件,在编译后会生成一个类,称为组件类。 生成的类的名称与文件名匹配。
因此,每个.razor文件,必须以大写字母开头,按照类名命名规范定义文件名称。

`.razor` ,以 `@code{}` 包含 C# 代码,这部分代码除了组件间可以使用,程序中也可以正常使用,因为属于类的一部分。

创建Test.razor文件,文件内容如下:

@code{ public string Name { get; set; } }

Pargrom 中:

Pages.Test test = new Pages.Test(); test.Name = "Blazor";

简单来说,就是可以作为一个类来使用。@code{}中定义的成员,就是类的成员。
成员正常使用 public 、private 等访问修饰符修饰。

静态资产

默认静态资源文件位置在项目的 wwwroot 目录,前端(.razor、.cshtml)等,默认寻址时,使用绝对路径/即可访问资源。
例如:

<img alt="Company logo" src="/images/logo.png" />

这个路径是要放到前端才能,由前端访问时 ASP.NET Core 框架自动处理,相当于前端访问/,后端访问D:/test/Blazor/wwwroot

路由与路由参数

页面组件使用@page设置此页面的访问地址,这里没有 Controller 和 Action 的分层和路由导航(相对地址),直接是一个绝对的访问地址,并且全局唯一。

Index.razor中,路由:

@page "/"

Blazor 不支持像 Controller 和 Action 那样设置灵活的 URL 可选参数(URL Query),例如:

[HttpGet("Test/{Id}")] public string Test([FromQuery]int Id) { return "123"; }

Blazor 如果想通过 URL Query 传递参数,可以使用{Name}

@page "/test" @page "/test/{Id}" <h2>@Id</h2> @code{ [Parameter] public string Id { get; set; } = "123"; }

因为 Blazor 不支持可选参数,因此,如果只设置@page "/test/{Id}",那么每次访问都必须带有这个参数值。
需要使用[Parameter]来修饰成员,才能捕获@page "/test/{Id}"
另外,理由参数是 string 类型,不能自动转为数值类型。不如会报错:

InvalidOperationException: Unable to set property 'Id' on object of type 'BlazorApp1.Pages.Test'. The error was: Unable to cast object of type 'System.String' to type 'System.Int32'.

你可以接收后,显式转为数值类型。

组件参数

@code代码块中,使用[Parameter]修饰的公共属性,那么这个属性就会标识为组件指定参数。
注意官网文档中,这个小节的代码示例,实际是不允许这样写得的。
目前,有两个地方需要使用[Parameter]特性,一个是前一小节的路由参数绑定,另一个是嵌入组件时使用。
示例:
Test.razor 文件内容:

<h2>@Title</h2> @code{ [Parameter] public string Title { get; set; } = "test"; }

别的组件嵌入Test.razor这个组件时,就可以使用 Title 传递参数进去:

<Test Title="111" />

请勿创建会写入其自己的组参数属性的组件

前面我们说到,[Parameter]特性的使用,这个特性时作为参数传递而使用的。
对于路由参数,其修饰的属性应该是privite,对于其它组件传递参数,属性应该设置为public
如果一个组件的@code{}成员不需要被外界作为参数使用,就应该设置为private
因为.razor一般不会作为类来使用。、;而且不设置[Parameter]的属性,别的组件也使用不了这个属性。

那么,文档说 “请勿创建会写入其自己的组参数属性的组件”,指定是[Parmeter]休息的属性,是作为参数传递使用的,不要在组件中修改这个属性的值。

如果实在要操作的话,可以先拷贝这个值,使用别的变量操作,示例:

<h2>@Title</h2> @code{ [Parameter] public string Title { get; set; } = "test"; private string _Title; protected override void OnInitialized() { _Title = Title; } }

这样,组件要操作的话,可以使用_Title,保留Title
OnInitalized()是一个组件初始化的方法,也可以理解成构造函数,可以参考docs.microsoft.com/zh-cn/aspnet/core/blazor/lifecycle?view=aspnetcore-3.1#component-initialization-methods

子内容

因为组件是可以嵌套的,可以要求另一个组件显示要求的内容。

  • 被多个组件使用,不同组件要呈现不一样的内容;
  • 要根据父组件的配置,显示子组件;
  • 组件 A 要求使用到的组件 B,显示其传递的内容;

简单来说,就是将页面内容作为复杂类型传递给另一个组件,要求这个组件显示出来。
那么,子内容指的是一个组件可以接收另一个组件的内容,使用RenderFragment来接收内容。
示例如下:
Test.razor中,内容:

<div>@Children</div> @code{ [Parameter] public RenderFragment Children { get; set; } }

另一个组件:

Blazor组件在ASP.NET Core中如何实现高效的前端开发?

@page "/" <Test Children=r /> @code{ private RenderFragment r =@<h1>测试子内容</h1>; }

RenderFragment的使用,请自行查阅资料。

属性展开

属性展开是使用字典类型表示一个 Html 标签的多个属性。

<input id="1" maxlength="@Maxlength" placeholder="@Placeholder" required="@Required" size="@Size" /> <input id="2" @attributes="InputAttributes" /> @code { #region private string Maxlength { get; set; } = "10"; private string Placeholder { get; set; } = "Input placeholder text"; private string Required { get; set; } = "required"; private string Size { get; set; } = "50"; #endregion // 使用字典键值对表示 public Dictionary<string, object> InputAttributes { get; set; } = new Dictionary<string, object>() { { "maxlength", "10" }, { "placeholder", "Input placeholder text" }, { "required", "required" }, { "size", "50" } }; }

任意参数

[Paramter]特性,只有一个属性,其定义如下:

public bool CaptureUnmatchedValues { get; set; }

文档说明:[Parameter] 上的 CaptureUnmatchedValues 属性允许参数匹配所有不匹配任何其他参数的特性。
其作用是通过字典接收在父组件中出现但是未在@code{}中定义的参数属性。
例如:
Test.razor

@code{ // 这个属性没有用,随便起个名字测试 [Parameter] public string A { get; set; } [Parameter(CaptureUnmatchedValues = true)] public IDictionary<string, object> AdditionalAttributes { get; set; } }

父组件中使用:

<Test A="A" B="B" C="C" />

B、C 都是Test.razor中没有出现过的,那么这些参数和参数值都会自动转为键值对存储到 AdditionalAttributes 中。

测试示例:
Test.razor中的内容

<ul> @foreach (var item in AdditionalAttributes) { <li>@item.Key - @item.Value</li> } </ul> @code{ // 这个属性没有用,随便起个名字测试 [Parameter] public string TTT { get; set; } [Parameter(CaptureUnmatchedValues = true)] public IDictionary<string, object> AdditionalAttributes { get; set; } }

其它组件使用:

@page "/" <Test TTT="ces" id="useIndividualParams" maxlength="10" placeholder="Input placeholder text" required="required" size="50" />

捕获对组件的引用

组件引用提供了一种引用组件实例的方法,使用@ref可以实现引用对参数的引用。
创建一个Test.razor文件,内容不限。
在一个组件中,引用该组件实例

@page "/" <Test @ref="_test" /> @code{ private Test _test; }

在使用Test.razor组件的同时,保留了引用,以便在@code{}中使用其成员。

在外部调用组件方法以更新状态

组件继承了 ComponentBase 类型,有个InvokeAsync方法可用于外界更新此 UI 的状态。

示例如下:
创建 MyUIServer 类型,

// 能够向所有正在打开的 Index.razor 页面发送通知 public static class MyUIServer { // 向所有人发送通知 public static async Task ToMessage(string message) { if (events != null) { await events.Invoke(message); } } public static void AddEvent(Func<string, Task> func) { events += func; } public static void RemoveEvent(Func<string, Task> func) { events -= func; } private static event Func<string, Task> events; }

Index.razor

@page "/" @using BlazorApp1.Data @implements IDisposable <input @bind="_message" /> <button @onclick="Btn">发送消息</button> <ul> @foreach (var item in messageList) { <li>@item</li> } </ul> @code { private string _message; private List<string> messageList = new List<string>(); // 进入页面时 protected override void OnInitialized() { MyUIServer.AddEvent(UIEvent); } // 退出当前页面UI后移除该事件 public void Dispose() { MyUIServer.RemoveEvent(UIEvent); } protected async Task UIEvent(string message) { // 组件自带的方法,用于外部调用更新状态 await InvokeAsync(() => { messageList.Add(message); StateHasChanged(); }); } // 向所有正在访问 Index.razor 页面发送消息 private async Task Btn() { await MyUIServer.ToMessage(_message); } }

打开多个窗口,访问页面localhost:5001/,在其中一个窗口输入内容并且点击按钮,即可将消息内容推送到其它窗口。

下面是一个修改官网示例的示例:
创建一个类型 NotifierService

public class NotifierService { public async Task Update(string key, int value) { if (Notify != null) { await Notify.Invoke(key, value); } } public event Func<string, int, Task> Notify; }

该类型的 Notify 可以绑定多个事件;通过调用Update()方法,可以触发各个事件。
在 Startup 中注入服务services.AddSingleton<NotifierService>();
Index.razor中,内容为:

@page "/" @using BlazorApp1.Data @inject NotifierService Notifier @implements IDisposable <p>Last update: @_lastNotification.key = @_lastNotification.value</p> @code { private (string key, int value) _lastNotification; protected override void OnInitialized() { Notifier.Notify += OnNotify; } public async Task OnNotify(string key, int value) { // 组件自带的方法,用于外部调用更新状态 await InvokeAsync(() => { _lastNotification = (key, value); StateHasChanged(); }); } // 退出当前页面UI后移除该事件 public void Dispose() { Notifier.Notify -= OnNotify; } }

Test.razor文件中:

@page "/test" @using BlazorApp1.Data @inject NotifierService Notifier Key: <input @bind="Key" /> Value: <input @bind="Value" /> <button @onclick="Update">更新</button> @code{ private string Key { get; set; } private int? Value { get; set; } private async Task Update() { await Notifier.Update(Key, Value.Value); Key = string.Empty; Value = null; } }

然后启动项目,一个页面打开localhost:5001/,另一个页面打开localhost:5001/test
test页面输入 Key 和 Value,点击按钮,即可通知到所有正在打开Index.razor的页面。

使用 @ 键控制是否保留元素和组件

在使用表格或了表等元素时,如果出现插入或删除、更新等情况,整个表格或列表,就会被重新渲染。这样会带来比较大的性能消耗。
一般使用绑定的元素,其更新是自动的,不需要人为控制。
在能保证每一项的某个元素列,都是唯一的时候,我们可以使用@key关键字来优化组件。
示例:

@page "/" @using BlazorApp1.Data Key: <input @bind="_key" /> Value: <input @bind="_value" /> <button @onclick="Add">添加</button> <button @onclick="Remove">移除</button> <ul> @foreach (var item in dic) { <li @key="item.Key">@item.Key - @item.Value</li> } </ul> @code { private int? _key; private int _value; private List<MyData> dic { get; set; } = new List<MyData>(); private void Add() { if (_key == null) return; dic.Add(new MyData { Key = _key.Value, Value = _value }); _key = null; } private void Remove() { if (_key == null) return; dic.Remove(dic.First(x => x.Key == _key.Value)); _key = null; } }

指定基类

@inherits指令可用于指定组件的基类。 组件都默认继承了 ComponentBase 。
示例:
创建文件TestBase.razor,内容如下

@code{ protected int Id { get; set; } }

创建Test.razor,文件内容如下

@inherits TestBase @code{ public int Get() { return Id; } }

指定属性

可以通过 @attribute 指令在 Razor 组件中指定组件的特性(属性)。 例如页面需要登录才能访问,则添加[Authorize]

@page "/" @attribute [Authorize]

导入组件

当要使用的组件与当前组件在同一个命名空间时,不需要“导入”,如果两者不在同一个命名空间,则可以使用@using导入此组件。

原始 HTML

使用 MarkupString 类型可以将字符串转为 HTML 元素对象。

@html @code{ public MarkupString html = (MarkupString)"<h1> Test </h1>"; }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。

本文共计3831个文字,预计阅读时间需要16分钟。

Blazor组件在ASP.NET Core中如何实现高效的前端开发?

目录+ 关于组件+ 组件类+ 静态资源+ 路由与路由参数+ 组件参数+ 创建会话写入组件参数+ 子内容+ 属性展开+ 任意参数+ 捕获组件引用+ 外部调用组件方法更新状态

目录
  • 关于组件
  • 组件类
  • 静态资产
  • 路由与路由参数
  • 组件参数
  • 请勿创建会写入其自己的组参数属性的组件
  • 子内容
  • 属性展开
  • 任意参数
  • 捕获对组件的引用
  • 在外部调用组件方法以更新状态
  • 使用 @ 键控制是否保留元素和组件
  • 指定基类
  • 指定属性
  • 导入组件
  • 原始 HTML

项目 Blazor 中,使用.razor结尾的文件,称为组件;而 Blazor 中的组件,正式名称是razor 组件;

Blazor 组件是 razor 过渡而来的,使用 razor 的基本语法特性,但是 Balzor 不支持 razor 中的标记帮助程序。

关于组件

.razor文件分为页面(带@page)和组件(不带@page,或者说页面组件和非页面组件。两者区别在于页面有路由,可以直接通过 URI 访问,一般放在 Page 文件夹中;而组件,作为一个部件,必须嵌入其它组件中,在页面中显示,一般放到 Shared 文件夹中,供多个页面共享、复用。
本文接下来所指的组件都是非页面组件。
.razor文件中,开头有@page标记的,就是页面组件,没有的就是非页面组件。
当然两者并没有严格的区分。
组件命名时,应该带上Component后缀。

组件类

每个.razor文件,在编译后会生成一个类,称为组件类。 生成的类的名称与文件名匹配。
因此,每个.razor文件,必须以大写字母开头,按照类名命名规范定义文件名称。

`.razor` ,以 `@code{}` 包含 C# 代码,这部分代码除了组件间可以使用,程序中也可以正常使用,因为属于类的一部分。

创建Test.razor文件,文件内容如下:

@code{ public string Name { get; set; } }

Pargrom 中:

Pages.Test test = new Pages.Test(); test.Name = "Blazor";

简单来说,就是可以作为一个类来使用。@code{}中定义的成员,就是类的成员。
成员正常使用 public 、private 等访问修饰符修饰。

静态资产

默认静态资源文件位置在项目的 wwwroot 目录,前端(.razor、.cshtml)等,默认寻址时,使用绝对路径/即可访问资源。
例如:

<img alt="Company logo" src="/images/logo.png" />

这个路径是要放到前端才能,由前端访问时 ASP.NET Core 框架自动处理,相当于前端访问/,后端访问D:/test/Blazor/wwwroot

路由与路由参数

页面组件使用@page设置此页面的访问地址,这里没有 Controller 和 Action 的分层和路由导航(相对地址),直接是一个绝对的访问地址,并且全局唯一。

Index.razor中,路由:

@page "/"

Blazor 不支持像 Controller 和 Action 那样设置灵活的 URL 可选参数(URL Query),例如:

[HttpGet("Test/{Id}")] public string Test([FromQuery]int Id) { return "123"; }

Blazor 如果想通过 URL Query 传递参数,可以使用{Name}

@page "/test" @page "/test/{Id}" <h2>@Id</h2> @code{ [Parameter] public string Id { get; set; } = "123"; }

因为 Blazor 不支持可选参数,因此,如果只设置@page "/test/{Id}",那么每次访问都必须带有这个参数值。
需要使用[Parameter]来修饰成员,才能捕获@page "/test/{Id}"
另外,理由参数是 string 类型,不能自动转为数值类型。不如会报错:

InvalidOperationException: Unable to set property 'Id' on object of type 'BlazorApp1.Pages.Test'. The error was: Unable to cast object of type 'System.String' to type 'System.Int32'.

你可以接收后,显式转为数值类型。

组件参数

@code代码块中,使用[Parameter]修饰的公共属性,那么这个属性就会标识为组件指定参数。
注意官网文档中,这个小节的代码示例,实际是不允许这样写得的。
目前,有两个地方需要使用[Parameter]特性,一个是前一小节的路由参数绑定,另一个是嵌入组件时使用。
示例:
Test.razor 文件内容:

<h2>@Title</h2> @code{ [Parameter] public string Title { get; set; } = "test"; }

别的组件嵌入Test.razor这个组件时,就可以使用 Title 传递参数进去:

<Test Title="111" />

请勿创建会写入其自己的组参数属性的组件

前面我们说到,[Parameter]特性的使用,这个特性时作为参数传递而使用的。
对于路由参数,其修饰的属性应该是privite,对于其它组件传递参数,属性应该设置为public
如果一个组件的@code{}成员不需要被外界作为参数使用,就应该设置为private
因为.razor一般不会作为类来使用。、;而且不设置[Parameter]的属性,别的组件也使用不了这个属性。

那么,文档说 “请勿创建会写入其自己的组参数属性的组件”,指定是[Parmeter]休息的属性,是作为参数传递使用的,不要在组件中修改这个属性的值。

如果实在要操作的话,可以先拷贝这个值,使用别的变量操作,示例:

<h2>@Title</h2> @code{ [Parameter] public string Title { get; set; } = "test"; private string _Title; protected override void OnInitialized() { _Title = Title; } }

这样,组件要操作的话,可以使用_Title,保留Title
OnInitalized()是一个组件初始化的方法,也可以理解成构造函数,可以参考docs.microsoft.com/zh-cn/aspnet/core/blazor/lifecycle?view=aspnetcore-3.1#component-initialization-methods

子内容

因为组件是可以嵌套的,可以要求另一个组件显示要求的内容。

  • 被多个组件使用,不同组件要呈现不一样的内容;
  • 要根据父组件的配置,显示子组件;
  • 组件 A 要求使用到的组件 B,显示其传递的内容;

简单来说,就是将页面内容作为复杂类型传递给另一个组件,要求这个组件显示出来。
那么,子内容指的是一个组件可以接收另一个组件的内容,使用RenderFragment来接收内容。
示例如下:
Test.razor中,内容:

<div>@Children</div> @code{ [Parameter] public RenderFragment Children { get; set; } }

另一个组件:

Blazor组件在ASP.NET Core中如何实现高效的前端开发?

@page "/" <Test Children=r /> @code{ private RenderFragment r =@<h1>测试子内容</h1>; }

RenderFragment的使用,请自行查阅资料。

属性展开

属性展开是使用字典类型表示一个 Html 标签的多个属性。

<input id="1" maxlength="@Maxlength" placeholder="@Placeholder" required="@Required" size="@Size" /> <input id="2" @attributes="InputAttributes" /> @code { #region private string Maxlength { get; set; } = "10"; private string Placeholder { get; set; } = "Input placeholder text"; private string Required { get; set; } = "required"; private string Size { get; set; } = "50"; #endregion // 使用字典键值对表示 public Dictionary<string, object> InputAttributes { get; set; } = new Dictionary<string, object>() { { "maxlength", "10" }, { "placeholder", "Input placeholder text" }, { "required", "required" }, { "size", "50" } }; }

任意参数

[Paramter]特性,只有一个属性,其定义如下:

public bool CaptureUnmatchedValues { get; set; }

文档说明:[Parameter] 上的 CaptureUnmatchedValues 属性允许参数匹配所有不匹配任何其他参数的特性。
其作用是通过字典接收在父组件中出现但是未在@code{}中定义的参数属性。
例如:
Test.razor

@code{ // 这个属性没有用,随便起个名字测试 [Parameter] public string A { get; set; } [Parameter(CaptureUnmatchedValues = true)] public IDictionary<string, object> AdditionalAttributes { get; set; } }

父组件中使用:

<Test A="A" B="B" C="C" />

B、C 都是Test.razor中没有出现过的,那么这些参数和参数值都会自动转为键值对存储到 AdditionalAttributes 中。

测试示例:
Test.razor中的内容

<ul> @foreach (var item in AdditionalAttributes) { <li>@item.Key - @item.Value</li> } </ul> @code{ // 这个属性没有用,随便起个名字测试 [Parameter] public string TTT { get; set; } [Parameter(CaptureUnmatchedValues = true)] public IDictionary<string, object> AdditionalAttributes { get; set; } }

其它组件使用:

@page "/" <Test TTT="ces" id="useIndividualParams" maxlength="10" placeholder="Input placeholder text" required="required" size="50" />

捕获对组件的引用

组件引用提供了一种引用组件实例的方法,使用@ref可以实现引用对参数的引用。
创建一个Test.razor文件,内容不限。
在一个组件中,引用该组件实例

@page "/" <Test @ref="_test" /> @code{ private Test _test; }

在使用Test.razor组件的同时,保留了引用,以便在@code{}中使用其成员。

在外部调用组件方法以更新状态

组件继承了 ComponentBase 类型,有个InvokeAsync方法可用于外界更新此 UI 的状态。

示例如下:
创建 MyUIServer 类型,

// 能够向所有正在打开的 Index.razor 页面发送通知 public static class MyUIServer { // 向所有人发送通知 public static async Task ToMessage(string message) { if (events != null) { await events.Invoke(message); } } public static void AddEvent(Func<string, Task> func) { events += func; } public static void RemoveEvent(Func<string, Task> func) { events -= func; } private static event Func<string, Task> events; }

Index.razor

@page "/" @using BlazorApp1.Data @implements IDisposable <input @bind="_message" /> <button @onclick="Btn">发送消息</button> <ul> @foreach (var item in messageList) { <li>@item</li> } </ul> @code { private string _message; private List<string> messageList = new List<string>(); // 进入页面时 protected override void OnInitialized() { MyUIServer.AddEvent(UIEvent); } // 退出当前页面UI后移除该事件 public void Dispose() { MyUIServer.RemoveEvent(UIEvent); } protected async Task UIEvent(string message) { // 组件自带的方法,用于外部调用更新状态 await InvokeAsync(() => { messageList.Add(message); StateHasChanged(); }); } // 向所有正在访问 Index.razor 页面发送消息 private async Task Btn() { await MyUIServer.ToMessage(_message); } }

打开多个窗口,访问页面localhost:5001/,在其中一个窗口输入内容并且点击按钮,即可将消息内容推送到其它窗口。

下面是一个修改官网示例的示例:
创建一个类型 NotifierService

public class NotifierService { public async Task Update(string key, int value) { if (Notify != null) { await Notify.Invoke(key, value); } } public event Func<string, int, Task> Notify; }

该类型的 Notify 可以绑定多个事件;通过调用Update()方法,可以触发各个事件。
在 Startup 中注入服务services.AddSingleton<NotifierService>();
Index.razor中,内容为:

@page "/" @using BlazorApp1.Data @inject NotifierService Notifier @implements IDisposable <p>Last update: @_lastNotification.key = @_lastNotification.value</p> @code { private (string key, int value) _lastNotification; protected override void OnInitialized() { Notifier.Notify += OnNotify; } public async Task OnNotify(string key, int value) { // 组件自带的方法,用于外部调用更新状态 await InvokeAsync(() => { _lastNotification = (key, value); StateHasChanged(); }); } // 退出当前页面UI后移除该事件 public void Dispose() { Notifier.Notify -= OnNotify; } }

Test.razor文件中:

@page "/test" @using BlazorApp1.Data @inject NotifierService Notifier Key: <input @bind="Key" /> Value: <input @bind="Value" /> <button @onclick="Update">更新</button> @code{ private string Key { get; set; } private int? Value { get; set; } private async Task Update() { await Notifier.Update(Key, Value.Value); Key = string.Empty; Value = null; } }

然后启动项目,一个页面打开localhost:5001/,另一个页面打开localhost:5001/test
test页面输入 Key 和 Value,点击按钮,即可通知到所有正在打开Index.razor的页面。

使用 @ 键控制是否保留元素和组件

在使用表格或了表等元素时,如果出现插入或删除、更新等情况,整个表格或列表,就会被重新渲染。这样会带来比较大的性能消耗。
一般使用绑定的元素,其更新是自动的,不需要人为控制。
在能保证每一项的某个元素列,都是唯一的时候,我们可以使用@key关键字来优化组件。
示例:

@page "/" @using BlazorApp1.Data Key: <input @bind="_key" /> Value: <input @bind="_value" /> <button @onclick="Add">添加</button> <button @onclick="Remove">移除</button> <ul> @foreach (var item in dic) { <li @key="item.Key">@item.Key - @item.Value</li> } </ul> @code { private int? _key; private int _value; private List<MyData> dic { get; set; } = new List<MyData>(); private void Add() { if (_key == null) return; dic.Add(new MyData { Key = _key.Value, Value = _value }); _key = null; } private void Remove() { if (_key == null) return; dic.Remove(dic.First(x => x.Key == _key.Value)); _key = null; } }

指定基类

@inherits指令可用于指定组件的基类。 组件都默认继承了 ComponentBase 。
示例:
创建文件TestBase.razor,内容如下

@code{ protected int Id { get; set; } }

创建Test.razor,文件内容如下

@inherits TestBase @code{ public int Get() { return Id; } }

指定属性

可以通过 @attribute 指令在 Razor 组件中指定组件的特性(属性)。 例如页面需要登录才能访问,则添加[Authorize]

@page "/" @attribute [Authorize]

导入组件

当要使用的组件与当前组件在同一个命名空间时,不需要“导入”,如果两者不在同一个命名空间,则可以使用@using导入此组件。

原始 HTML

使用 MarkupString 类型可以将字符串转为 HTML 元素对象。

@html @code{ public MarkupString html = (MarkupString)"<h1> Test </h1>"; }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。