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的语法的时候,有如下两个需要特别注意的地方:
指令(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。
注意不要重复。
参数覆盖
这个是一个规则,最佳编程实践:定义的参数对于本组件而言最好是只读参数。也即不要在本组件中对参数值进行更新,只能让调用者进行更新,如果确实要保持组件的状态,可以重新定义一个字段或者属性,然后在方法中对状态进行更新。切记。
应用特性
例如:
有条件渲染标记属性
看代码:
如果IsCompleted是true, 那么会渲染
否则就渲染为:
Razor模板
Razor模板的语法如下:
看如下的实例:
Razor模板的变量类型必须是RenderFragment.
静态资源
组件默认可以直接使用wwwroot中的静态资源的,例如:
空白移除
默认组件是移除头和尾的空白的,除非如下定义:
如果有CSS的需求,可以指定组件打开,如果需要全部打开,则可以将该指令加入到_Imports.razor组件中。