Skip to main content

Blazor组件基础之概述

分类:  Blazor入门 标签:  #Asp.Net core基础 #.Net #Web #Web Client #Blazor 发布于: 2023-05-27 9:53:21

那么从本章开始,我们开始学习Blazor组件的基础知识,希望大家能够快速的掌握Blazor这门新兴的技术框架

所有的Blazor应用都是基于Blazor组件来开发的,Blazor组件就是Razor的组件,以.razor为扩展名,同时包括HTML标记以及以@code {} 代码块包含的C#代码:HTML 标记,字段,属性,以及方法, 事件等。

Blazor中组件和Razor的组件可以等同。

Razor语法

我们上面说了Blazor组件实际上就是Razor组件,因此熟悉Razor语法是必须的,如果你对Razor语法还不熟悉,那么你可以参考我之前翻译的一篇Razor语法的文档,请使用如下链接访问:

Razor语法参考

在回顾Razor的语法的时候,有如下两个需要特别注意的地方:

  • 指令(Directives):  以@+保留关键字,例如@page 用于指定路由,@using 用于导入额外的软件包,@inject 注入服务等等。

  • 属性指令(Directives     Attributes):  在标记中用于指定属性的指令,例如<ChildComponent     @bind="OnChange"/> 这里 @bind就是属性指令,是用于标记中的属性的。主要用于改变标记或者组件的动作或者属性等等。

名字

组件的名字第一个字母必须是大写,这是强制规定的。重要的事情要多说几遍,组件的名字第一个字母必须大写!!

路由

这个部分请参考我们之前的文章:

组件包含两类组件,一类是带路由的组件,另外一类是不带路由的组件,同时也可以将组件分为另外两类:一类是输出显示的问题,另外一类是不输出显示的类。

另外类是可以带入参数,以及路由参数。关于路由参数请仔细参考上面的文章。

 

标记(特指类HTML的标记)和部分类支持

组件的UI是使用HTML标记来定义的,动态的渲染是使用嵌入的C#代码片段来完成的,这个部分就是Razor(请仔细回顾Razor的语法), 组件的其他成员定义在@code {} 块中,一个组件中可以定义多个@code {} 块,同时需要注意的是对于组件的定义有两种方式:

  • 混合HTML和 @code {} 块

  • UI单独使用HTML 定义,其他的成员使用部分类来定义,但是有一点需要注意,我们在blazor应用中使用_Imports.razor 全局导入引用的包,但是如果你自定定义了部分类之后,_Imports.razor中引入的包在部分类中不能共享,需要在部分类中重新定义,例如如下的组件Counter定义:



    需要注意的是部分类的类文件名是Counter.razor.cs,  也即是组件名.razor.cs.
    同时需要在部分类的定义中引入包:


组件的名称空间

对于组件的名称空间有两种形式指定:一种是根据约定指定名称空间,一种是使用指令@namespace显式的指定名称空间。

  • 根据约定指定名称空间:以项目的根名称空间+组件所在的目录路径:例如组件在项目HelloWorld的目录路径:./Pages/Order/Compontent.razor,     下,那么默认该组件的名称空间就是HelloWorld.Pages.Order, 全限定名称是HelloWorld.Pages.Order.Component。

  • 在页面中使用指令定义名称空间:

需要注意:

  • 不支持global::

  • 不支持using别名,也即@using     calss1 = class2, 不支持。

  • 不支持部分名称空间名。


指定组件的基类

组件默认的基类是ComponentBase,但是你可以指定自己组件的基类,只需要通过@inherits,  例如:



使用组件

使用HTML标记的形式使用组件,如下图:


组件内部也可以调用其他的组件,例如如下图:



参数

参数部门我们这里学习的参数主要是指两类的参数,一类是路由参数,另外一类是组件参数。

关于路由参数,请参考文章路由部分:

我们这里学习组件参数,组件需要在@code {} 部分用public修饰定义的自动属性,参数的类型有简单类型也可以是复杂的复合类型。同时需要使用特性[Parameter]来定义组件参数。如下图:


在指定参数的同时也可以指定默认值:


当在调用组件的时候,赋予调用组件的字段,属性或者方法的时候,在属性中需要使用@指定,例如:


需要注意的是在blazor组件中不能像razor组件中,razor的表达式中不能使用异步。同时组件的参数必须是自动属性,同时不能在get, set方法中加入逻辑。


组件内容的传递

Blazor组件能够给另外一个组件传递内容,方法如下:


需要注意的是,属性名必须是ChildContent,  然后这个变量的名称必须是RenderFragment.   在父组件中传入内容的方法如下:


可以向组件传入任意的参数,如果要向组件传入任意参数需要使用指令:@attributes,  来指定。例如:


有几个需要注意的地方,如果需要定义任意参数,参数的类型要么是:Dictionary<string,object> 要么是IEnumerable<KeyValuePair<string,object>> 或者IReadOnlyDictionary<string, object>这几个类型。

另外需要注意的是如果是组件参数,那么要注意指定选项:


否则会提示参数定义不存在。

另外有一个知识点:组件的参数是从右到左来处理的。如下实例,我们有一个ParentComponent,有一个ChildComponent,我们在ParentCompoent中调用ChildComponent

ParentComponent.razor:


ChildComponent.razor


大家觉得这个组件渲染出来是什么结果?


在这里我们需要注意的是我们这里的概念是渲染,而且渲染的顺序是从右到左,在父类中渲染的时候,ChildComonent中最右边是一个自有的extra属性,并且该属性是=5,因此渲染完成之后,再处理属性,但是由于已经有同名的,因此该调用参数被丢弃。

如果如如下定义:


应用上述的理论,这次渲染后的结果是:



获取组件的引用

我们可以获取组件的引用,但是需要注意的是只有当组件完成了渲染,才能获取组件的引用,获取到组件的引用了之后,可以调用组件相应的方法。我们通过使用@ref指令来引用组件的实例。



线程的同步上下文

关于线程的同步上下文,这个部分我会另开一个文章来仔细的讨论这个问题,这个是一个非常关键的技术工具,目前在Blazor中我们只需要注意的一件事是,渲染组件是在单一的线程中完成的,因此在组件渲染中,不能调用如下的方法:

  • Result

  • Wait

  • WaitAny

  • WaitAll

  • Sleep

  • GetResult

需要注意的是我们这里指的是组件渲染的时候,要仔细的区分一下组件渲染和生命周期方法。

组件渲染指的是在UI部分的C#代码,生命周期部分指的是@code {} 这里您可以使用异步方法。但是这些方法完成后,也是通过线程同步上下文完成组件的更新的。

 

使用@key关键字

@key关键字的主要应用场景是在渲染列表的时候,可以使用@key关键字,用于保留UI和数据之间的同步,加入UI中绑定的数据如果被其他方法编辑或者删除也需要UI做出相应的改变,即可以通过@key 关键字来完成。

@key关键字的值:

  • 列表项目中需要渲染的对象,可以直接使用

  • 列表项目中需要渲染的对象的唯一关键字,例如ID

注意不要重复。


参数覆盖

这个是一个规则,最佳编程实践:定义的参数对于本组件而言最好是只读参数。也即不要在本组件中对参数值进行更新,只能让调用者进行更新,如果确实要保持组件的状态,可以重新定义一个字段或者属性,然后在方法中对状态进行更新。切记。


应用特性

例如:



有条件渲染标记属性

看代码:


如果IsCompletedtrue 那么会渲染


否则就渲染为:


Razor模板

Razor模板的语法如下:


看如下的实例:

Razor模板的变量类型必须是RenderFragment.


静态资源

组件默认可以直接使用wwwroot中的静态资源的,例如:



空白移除

默认组件是移除头和尾的空白的,除非如下定义:


如果有CSS的需求,可以指定组件打开,如果需要全部打开,则可以将该指令加入到_Imports.razor组件中。