官方文档原文位置:

https://docs.microsoft.com/zh-cn/aspnet/core/blazor/components?view=aspnetcore-3.1

本文并不是独立教程的文章,而是属于对微软文档的讲解和说明。

组件:项目 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() 是一个组件初始化的方法,也可以理解成构造函数,可以参考 https://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; }
}

另一个组件:

@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);
} }

打开多个窗口,访问页面 https://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;
}
}

然后启动项目,一个页面打开 https://localhost:5001/ ,另一个页面打开 https://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>";
}

Blazor入门:ASP.NET Core Razor 组件的更多相关文章

  1. Blazor入门笔记(6)-组件间通信

    1.环境 VS2019 16.5.1.NET Core SDK 3.1.200Blazor WebAssembly Templates 3.2.0-preview2.20160.5 2.简介 在使用B ...

  2. C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式

    C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...

  3. .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/9985451.html 本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新 ...

  4. net core体系-web应用程序-4asp.net core2.0 项目实战(CMS)-第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了   原文链接:https://www.cnblogs.com/yilezhu/p/9985451.ht ...

  5. ASP.NET Core - Razor 页面简介

    简介 随着ASP.NET Core 2 即将来临,最热门的新事物是Razor页面.在之前的一篇文章中,我们简要介绍了ASP.NET Core Razor 页面. Razor页面是ASP.NET Cor ...

  6. ASP.NET Core Razor 页面使用指南

    ASP.NET Core Razor 页面作为 ASP.NET Core 2.0的一部分发布,它是基于页面的全新的Web开发框架.如果您想学习如何使用 ASP.NET Core Razor 页面,可以 ...

  7. 学习ASP.NET Core Razor 编程系列一

    一. 概述 .NET Core 1.0发布的时候就想进行学习的,不过根据微软的以往的发布规律1.0版可以认为是大众测试版,2.0才算稳定.现在2.1都已经发布了预览版,之前对其"不稳定&qu ...

  8. 学习ASP.NET Core Razor 编程系列六——数据库初始化

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  9. ASP.Net Core Razor+AdminLTE 小试牛刀

    AdminLTE 一个基于 bootstrap 的轻量级后台模板,这个前端界面个人感觉很清爽,对于一个大后端的我来说,可以减少较多的时间去承担前端的工作但又必须去独立去完成一个后台系统开发的任务,并且 ...

随机推荐

  1. 忍不住还是手写了一遍博客的css

    F12边调边改,的一点一点撸出来这个效果.感觉已经可以了.日历感觉没什么用直接隐藏了.

  2. mac上安装htop

    对于经常在mac上使用top命令的童鞋来说,htop会是一个更加好看和更加好用的命令,下面就是在mac上安装htop的步骤 1.首先去htop官网去下载,我下的是最新的2.2.0版本,网址是https ...

  3. IN612 IN612L蓝牙5.0 SoC芯片替换NRF52832/NRF52840

    IN612L是美国公司INPLAY的SOC产品系列之一,具有多模协同2.4G无线协议栈,支持2.4G私有协议栈以及蓝牙5.0全协议栈的SOC芯片.如2mbps高数据速率模式,125kbps/500kb ...

  4. vue使用trackingjs

    前言:因为公司是做人工智能-AI的,所有一个web数据平台为了装X,需要做个人脸登陆.前台需要把人脸的base64发给后台去做人脸校验. 功能很简单,需要注意的是web需要实现“调用摄像头”和“自动拍 ...

  5. Springboot:员工管理之公共页面提取 高亮显示(十(5))

    把顶部和左侧的公共代码分别放到header.html和left.html中 顶部代码:resources\templates\header.html 主内容展示: <!DOCTYPE html& ...

  6. LABEL和UUID

    基本用法 blkid 查看LABEL # blkid -s LABEL /dev/hda3: LABEL="/" /dev/hda1: LABEL="/boot1&quo ...

  7. TensorFlow-keras 100分类

    import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' from tensorflow.python.keras.datasets import cifa ...

  8. 大数据作业之利用MapRedeuce实现简单的数据操作

    Map/Reduce编程作业 现有student.txt和student_score.txt.将两个文件上传到hdfs上.使用Map/Reduce框架完成下面的题目 student.txt 20160 ...

  9. Git基本操作和使用

    基本命令: git config git init git clone git remote git fetch git commit git rebase git push 本地基本操作: git ...

  10. Adobe Flash player 过期

    完美解决问题的办法,在百度中输入 "adobe flash player debugger",如图进入官网 选择对应操作系统的对应版本,下载安装,重启浏览器,一切ok IE内核浏览 ...