官方文档原文位置:

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. Julia基础语法字符和字符串

    1.Julia字符串  2.字符

  2. Bug Bash in Personal Photo Experience 1/11/2016

    In the process of our Personal Photo Experience Project, There are some bugs which hinder our forwar ...

  3. python3+selenium3自动化1——元素定位

    1.selenium的webdriver提供了八种基本的元素定位方法 打开浏览器 driver = webdriver.Chrome() driver.get('https://www.baidu.c ...

  4. [转载]深度理解Session

    什么是session session的官方定义是:Session:在计算机中,尤其是在网络应用中,称为“会话控制”.Session 对象存储特定用户会话所需的属性及配置信息. 说白了session就是 ...

  5. Springboot:员工管理之删除员工及退出登录(十(9))

    springboot2.2.6 delete请求报错,降至2.1.11功能可用 原因未知 构建员工删除请求 com\springboot\controller\EmployeeController.j ...

  6. SQL Server 之T-SQL基本语句 (1)

    花了一天的时间看完了一本<SQL必知必会>,举个范例,来总结一下零碎的知识点.一般关于数据库操作的项目都会涉及到数据库的基本查询语句.在这里面就主要讲解一些基本常用的sql使用方法. 注: ...

  7. 2020/4/26 大数据的zookeeper分布式安装

    大数据的zookeeper分布式安装 **** 前面的文章已经提到Hadoop的伪分布式安装.现在就在原有的基础上安装zookeeper. 首先启动Hadoop平台 [root@master ~]# ...

  8. CSS躬行记(7)——合成

    在图形编辑软件中,可以按特定地方式处理不同图层的合成,最新的CSS规范也引入了该功能,并提供了mix-blend-mode和background-blend-mode两个属性.混合模式(blendin ...

  9. Ubuntu下的eclipse配置MapReduce

    下载配置文件: 链接:https://pan.baidu.com/s/13vatPHpDP5HaW0mKuHydUA提取码:pjxi 1)启动hadoop cd /usr/local/hadoop . ...

  10. Centos 7服务器搭建MySQL(mariadb)服务

    1.下载并安装MySQL yum install mariadb mariadb-server -y 2.启动MySQL systemctl start mariadb 3.对mariadb进行初始化 ...