第三章 组件(1)- 概述

server/2024/10/20 16:02:59/

注意,从这里开始,往后的文章中,Blazor项目指的都是Blazor Web App下的Server模式。

组件的基类

组件是使用 C# 和 HTML 标签的组合在 Razor 组件文件(文件扩展名为 .razor)中实现的。

默认情况下,ComponentBase是Razor组件的基类,该基类实现了组件的最低抽象接口,即IComponent接口,定义了组件最基本的属性和方法,例如,处理一组内置组件生命周期事件。

  • 可以看出,实际上组件就是一个C#类。

开发人员可以通过 Razor 组件文件 (.razor) 来构建 Razor 组件或者通过创建C#类型并继承ComponentBase来构建组件。此外,也可以通过实现IComponent来生成组件,从而对组件更加高度自定义的控制,但是实现IComponent就需要开发人员使用事件和生命周期方法手动触发渲染,且这些事件和方法必须由开发人员创建和维护。

Razor 语法

组件中可以使用 Razor 语法,其中会较为频繁使用了两个 Razor 功能,即指令和属性指令。

指令

Razoe指定用于更改组件标记的分析或运行方式。 例如,[@page](https://learn.microsoft.com/zh-cn/aspnet/core/mvc/views/razor?view=aspnetcore-8.0#page) 指令使用路由模板指定可路由组件,可以由用户请求在浏览器中按特定 URL 直接访问。
官方给了在组件中使用各种指令时的排放顺序规范,但并不是必须这么去排序的,具体如下:

  • @page
  • @rendermode(.NET 8 或更高版本)
  • @using
    • System 命名空间(字母顺序)
    • Microsoft 命名空间(字母顺序)
    • 第三方 API 命名空间(字母顺序)
    • 应用命名空间(字母顺序)
  • 其他指令(字母顺序)

然后,指令和Razor标记的第一行之间,留一个空白行。

  • 示例

    @page "/doctor-who-episodes/{season:int}"
    @rendermode InteractiveWebAssembly
    @using System.Globalization
    @using System.Text.Json
    @using Microsoft.AspNetCore.Localization
    @using Mandrill
    @using BlazorSample.Components.Layout
    @attribute [Authorize]
    @implements IAsyncDisposable
    @inject IJSRuntime JS
    @inject ILogger<DoctorWhoEpisodes> Logger<PageTitle>Doctor Who Episode List</PageTitle>...
    

属性指令

属性指令一般也是用于更改嘴贱元素的分析方式或运行方式的。

  • 示例

    <input @bind="episodeId" />
    

组件的名称、类名和命名空间

命名规则

  • 组件的名称必须以大写字符开头。
  • 文件路径和文件名建议使用Pascal大小写,例如Components/Pages/ProductDetail.razor
  • 可路由组件的URL路径,建议使用kebab大小写,例如"/product-detail"

命名空间规则

  • 可路由的组件通常位于 Components/Pages 文件夹中。
  • 非可路由组件(也就是没有用@page指令的组件)通常放置在 Components 文件夹或添加到项目的自定义文件夹中。
  • 组件的命名空间是从应用的根命名空间和该组件在项目内的位置(文件夹)派生而来的。 例如应用的根命名空间是 BlazorSample,并且 Counter 组件位于 Components/Pages 文件夹中:Counter 组件的命名空间为 BlazorSample.Components.Pages组件的完全限定类型名称为 BlazorSample.Components.Pages.Counter
  • 可以使用完全限定名来引用组件,这时不需要@using命令导入命名空间,例如:<BlazorSample.Components.Pages.Counter/>
  • 对于保存组件的自定义文件夹,最好使用 @using 指令添加到父组件或项目的 _Imports.razor 文件全局引用。需要注意的是,_Imports.razor 文件中的 @using 指令仅适用于 Razor 文件 (.razor),而不适用于 C# 文件 (.cs)。
  • 不支持global::
  • 不支持使用@using只引入部分命名空间,然后补全引用组件。例如,组件Components/Layout/NavMenu.razor,不能在要使用NavMenu组件组件上,通过@using BlazorSample.Components引入部分命名空间,然后通过<Layout.NavMenu></Layout.NavMenu>来引用组件
  • 不支持@using的别名指定,例如不支持@using AAA=BlazorApp7.Components.Layout

支持分部类

Blazor项目中的组件,本质就是继承了ComponentBase的C#类,既然是C#类,那么就支持分部类。

一般情况下,为了方便,Razor标签、HTML和@code块都放在同一个.razor文件中,例如Blazor项目模板中生成的Counter.razor组件。但当我们组件中相关业务逻辑较多较复杂时,全部都写在一个.razor文件中不免显得有些臃肿,这个时候就可以通过分部类,将C#相关的代码放置到部分类中。

组件的分部类的文件名建议名为xxxx.razor.cs,类似css隔离的用法。以项目模板中的Counter.razor组件为例子,将其中的计数方法和属性剥离到分部类中:

在这里插入图片描述

  • Counter.razor

    @page "/counter"
    @rendermode InteractiveServer<PageTitle>Counter</PageTitle><h1>Counter</h1><p role="status">Current count: @currentCount</p><button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
  • Counter.razor.cs

    using Microsoft.AspNetCore.Components;namespace BlazorServer.Components.Pages
    {public partial class Counter{private int currentCount = 0;private void IncrementCount(){currentCount++;}}
    }

指定基类

@inherits指令用于指定组件的基类。 与使用分部类不同,分部类仅在 C# 逻辑上拆分组件,而使用基类可以继承 C# 代码,以便在具有共同特征的组件之间共用基类的属性和方法。

  • BlazorRocks.razor

    @page "/blazor-rocks-"
    @inherits BlazorRocksBase<PageTitle>Blazor Rocks!</PageTitle><h1>Blazor Rocks! Example 1</h1><p>@BlazorRocksText
    </p>
    
  • BlazorRocksBase.cs

    using Microsoft.AspNetCore.Components;namespace BlazorSample;public class BlazorRocksBase : ComponentBase
    {public string BlazorRocksText { get; set; } ="Blazor rocks the browser!";
    }
    

async方法不支持返回void

Blazor框架不跟踪返回void的异步方法 (async),如果返回void,则不会捕获异常。 因此,建议始终从异步方法返回Task

组件实例的引用

Blazor提供了一种引用组件实例的方法,为的是方便在使用组件时,父组件可以通过组件实例调用对应的方法,从而更加灵活的使用组件

使用方式

  • 定义与目标组件类型相同的字段。
  • 使用目标组件时,以内联的方式,使用@ref属性指令设置对应的字段名称。

注意

组件引用仅在渲染组件后才开始赋值。在组件渲染完成之前,没有任何可以引用的内容,因此如果要调用组件引用中的方法时,要考虑正确的调用时机。

  • 不要直接在组件的事件中调用组件引用的方法,因为在分配单击事件时可能不会分配引用变量,例如<MyComponent @onclick="childComponent!.ChildMethod(5)"/>
  • 若要在组件完成渲染后操作组件引用,可以使用OnAfterRenderOnAfterRenderAsync方法。

示例

  • ReferenceChild.razor

    @inject ILogger<ReferenceChild> Logger@if (value > 0)
    {<p><code>value</code>: @value</p>
    }@code {private int value;public void ChildMethod(int value){Logger.LogInformation("Received {Value} in ChildMethod", value);this.value = value;StateHasChanged();}
    }
    
  • ReferenceParent.razor

    @page "/reference-parent"<div><button @onclick="@(() => childComponent1!.ChildMethod(5))">Call <code>ReferenceChild.ChildMethod</code> (first instance) with an argument of 5</button><ReferenceChild @ref="childComponent1"/>
    </div><div><button @onclick="CallChildMethod">Call <code>ReferenceChild.ChildMethod</code> (second instance) with an argument of 5</button><ReferenceChild @ref="childComponent2"/>
    </div>@code {private ReferenceChild? childComponent1;private ReferenceChild? childComponent2;private void CallChildMethod(){childComponent2!.ChildMethod(5);}
    }
    

http://www.ppmy.cn/server/4937.html

相关文章

设计模式代码实战-桥接模式

1、问题描述 小明家有一个万能遥控器&#xff0c;能够支持多个品牌的电视。每个电视可以执行开机、关机和切换频道的操作&#xff0c;请你使用桥接模式模拟这个操作。 输入示例 6 0 2 1 2 0 4 0 3 1 4 1 3 输出示例 Sony TV is ON TCL TV is ON Switching Sony TV channel S…

命令模式:将请求封装为对象

在软件工程中&#xff0c;设计模式是解决常见问题的成熟模板。命令模式&#xff08;Command Pattern&#xff09;是这些设计模式之一&#xff0c;它属于行为型模式&#xff0c;用于将一个请求封装为一个对象&#xff0c;从而允许用户使用不同的请求、队列或日志请求来参数化其他…

Redis:发布和订阅

文章目录 一、介绍二、发布订阅命令 一、介绍 Redis的发布和订阅功能是一种消息通信模式&#xff0c;发送者&#xff08;pub&#xff09;发送消息&#xff0c;订阅者&#xff08;sub&#xff09;接收消息。这种功能使得消息发送者和接收者不需要直接建立连接&#xff0c;而是通…

ArcGIS加载的各类地图怎么去除服务署名水印

昨天介绍的&#xff1a; 一套图源搞定&#xff01;清新规划底图、影像图、境界、海洋、地形阴影图、导航图-CSDN博客文章浏览阅读373次&#xff0c;点赞7次&#xff0c;收藏11次。一体化集成在一起的各类型图源&#xff0c;比如包括影像、清新的出图底图、地形、地图阴影、道路…

【Linux】提升Linux命令行效率:光标移动和文本操作的键盘快捷键

Just 那么年少 还那么骄傲 两眼带刀 不肯求饶 即使越来越少 即使全部都输掉 也要没心没肺地笑 Just 那么年少 我向你招手 让你看到 我混账到老 天涯海角 天荒地老 只等你摔杯为号 &#x1f3b5; 朴树《Forever Young》 Linux命令行界面&#xff08;CLI&am…

英伟达大跳水!一夜暴跌10%,市值蒸发2000亿

相信大家已经在各大社交平台上看到了&#xff0c;英伟达一夜蒸发了2000亿美元&#xff01; GPT-3.5研究测试&#xff1a; https://hujiaoai.cn GPT-4研究测试&#xff1a; https://higpt4.cn Claude-3研究测试&#xff08;全面吊打GPT-4&#xff09;&#xff1a; https://hic…

Swift文件与IO操作

在Swift中&#xff0c;我们可以通过文件路径或URL进行文件的读写操作。文件路径是文件在文件系统中的位置&#xff0c;可以是绝对路径或相对路径。URL是统一资源定位符&#xff0c;可以指向本地文件或远程资源。 从文件路径或URL获取文件内容&#xff1a; let filePath "…

http 3.0 有哪些新特性

HTTP/3 是超文本传输协议&#xff08;HTTP&#xff09;的最新主要版本&#xff0c;其显著特点是放弃了传统的TCP作为传输层协议&#xff0c;转而采用基于UDP的QUIC&#xff08;Quick UDP Internet Connections&#xff09;协议。以下是HTTP/3利用QUIC实现高性能传输的关键特性&…