.NET8 Blazor 从入门到精通:(一)关键概念

最近在学习 Blazor ,在B站上找了一个国外的课程边看边学习。嗯,原价¥1503的课程,大概200多美元,课程链接如下:

B站(大章节分P-适合初学):.NET 8 Blazor 从入门到精通

B站(小章节分P-适合复习):Blazor从入门到精通(中文字幕)

官网课程:Blazor From Start to Finish

image

Blazor 的关键概念#

本文主要介绍Blazor 的关键概念,每个知识点都附上了学习过程中查到的参考资料。文中删除了一些常识性或表述不清的内容,如热重载、组件与页面等。

项目模板#

项目开发的常用模板配置项如下,其它配置也可以都试一下,观察一下区别:
image

Auto 交互方式:最初使用 Blazor Server,并在随后访问时使用 WebAssembly 自动进行交互式客户端呈现,详细内容参考.NET8 Blazor的Auto渲染模式的初体验

Razor 语法#

参考 ASP.NET Core 的 Razor 语法参考,前期主要理解下面几个重点语法即可:

  • 隐式 Razor 表达式:以 @ 开头,后跟 C# 代码
<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>
  • 显式 Razor 表达式:由 @ 符号和圆括号组成
<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>
  • @code 块:允许 Razor 组件将 C# 成员(字段、属性和方法)添加到组件
@code {
    // C# members (fields, properties, and methods)
}
  • 循环语句和条件语句:如 @for@if 等,直接写在页面中
@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

依赖注入#

参考 将依赖项注入 Blazor 组件Program.cs(项目引导程序) 中注册依赖项:

builder.Services.AddSingleton<DemoDependency>();
//用于注册依赖项的其他模式...

对于 Blazor 组件,有两种方法可以指示我们的组件使用哪些依赖项:

//1.在 Razor 标记中
@inject IToDoApi ToDoApi
@inject ISomeServiceType AnotherService

//2.在 C# 代码中
@code
{
  [Inject]
  private IYetAnotherServiceType PropertyInjectedDependency { get; set; }
}

注入配置#

参考 ASP.NET Core Blazor 配置 ,其中配置的优先级别:用户机密 > appsettings.{Environment}.json > appsettings.json

在 appsettings.json 中配置连接字符串:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "Default": "连接字符串来自appsettings.json"
  }
}

在组件中引入配置依赖:

@page "/"
@inject IConfiguration config

<PageTitle>Home</PageTitle>

<h1>Hello, world!</h1>
<h2>@config.GetConnectionString("Default")</h2>

IConfiguration 是默认注册的,不需要另外写代码注册,可以直接使用。

HeadOutlet 组件#

切换页面时不是整个页面被重新加载,实际上只有根组件 App.razor<Routes /> 被重新渲染。这种渲染方式不利于SEO,可以使用 HeadOutlet 组件来控制 <head> 元素的内容来进行优化。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <base href="/" />
    <link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
    <link rel="stylesheet" href="app.css" />
    <link rel="stylesheet" href="KeyConcepts.styles.css" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <HeadOutlet />
</head>

<body>
    <Routes />
    <script src="_framework/blazor.web.js"></script>
</body>

</html>

参考 在 ASP.NET Core Blazor 应用中控制 <head> 内容,指定一个页面的标题和描述:

@page "/control-head-content"

<PageTitle>@title</PageTitle>
<p>Title: @title</p>
<p>Description: @description</p>

<HeadContent>
    <meta name="description" content="@description">
</HeadContent>

@code {
    private string description = "This description is set by the component.";
    private string title = "Control <head> Content";
}
  • 使用 PageTitle 组件指定页面标题,这样可以将 HTML <title> 元素呈现给 HeadOutlet 组件。
  • 使用 HeadContent 组件指定 <head> 元素内容,该组件为 HeadOutlet 组件提供内容。

需要注意,如果在A页面用了B页面,那么B页面的 PageTitle 会覆盖掉A页面的 PageTitle。所以,组件不需要作为页面使用时就不要放 PageTitle 了。

@code 分离#

Blazor可以支持在razor文件里面添加cs代码,但是代码一旦复杂了之后就会变得特别的麻烦。其实,这部分代码在编译时实际是被分离出来的,我们也可以在编译前手动将它们分离出来。

右键 code ,选择 快速操作和重构 ,然后如下图所示选择 将块提取到代码隐藏中
image

结果如下,其中①只是②的一个快捷方式:
image

上面是使用VS的自动分离功能,也可以使用手动的方式进行分离。参考 C# Blazor 学习笔记(4):blazor代码分离,注意以下几点:

  • 直接右键razor组件的上级目录,添加一个partial局部类
  • 新建类的类名是xxx.razor.cs,这样才能挂到组件上面
xxx.razor
xxx.razor.cs:代码
xxx.razor.css:css样式

代码分离后,依赖项也需要改成属性注入:

using Microsoft.AspNetCore.Components;

namespace KeyConcepts.Client.Pages;

public partial class Demo
{
    // 在razor组件中是这样的 @inject IConfiguration config
    [Inject]
    protected IConfiguration config { get; set; }=default!;

    private string? GetConnectionString()
    {
        return config.GetConnectionString("Default");
    }
}

Blazor 调试#

调试没什么好说的,就在VS中正常打断点、单步运行、监控变量值就行了,具体参考 调试 ASP.NET Core 应用

CSS 隔离#

CSS 隔离可以将 CSS 范围限定到 Razor 组件,以简化 CSS 并避免与其他组件或库发生冲突,但过多的使用也会导致 CSS 追踪困难。

参考 ASP.NET Core Blazor CSS 隔离 ,在与组件相同文件夹中创建一个 .razor.css 文件,该文件与组件的 .razor 文件的名称相匹配。例如为 Counter.razor 组件创建一个 Counter.razor.css 文件:

h1 {
    color:red;
}

生成时 Blazor 会重写 CSS 选择器以匹配组件呈现的标记, 重写的 CSS 样式被作为静态资产捆绑和生成, 默认情况下在 <head> 标记中引用表样式:

<!-- {ASSEMBLY NAME} 占位符是项目的程序集名称 !-->
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">

在捆绑的文件中,每个组件都与范围标识符关联。 对于每个具有样式的组件,HTML 属性追加有格式 b-{STRING},其中 {STRING} 占位符是框架生成的十个字符的字符串。 标识符对每个应用都是唯一的。

在呈现的 Counter 组件中,Blazor 将范围标识符追加到 h1 元素:

<h1 b-zdeg3nv67a="">Counter</h1>

image

注:如果CSS不生效,需要清理一下浏览器的缓存。

调用JavaScript#

js文件可以放到wwwroot目录下,也可以关联到特定组件,参考
从与组件并置的外部 JavaScript 文件 (.js) 加载脚本 为 Counter 组件添加并置js文件:

//Counter.razor.js
export function displayCount(count) {
    alert('The count is' + count);
}

export function createMessage(count) {
    return 'The count is' + count;
}

Blazor 应用的 Razor 组件使用 .razor.js 扩展名并置 JS 文件(参考 CSS 隔离部分),并且可通过项目中文件的路径公开寻址 {PATH}/{COMPONENT}.razor.js

  • 占位符 {PATH} 是指向组件的路径
  • 占位符 {COMPONENT} 是组件

修改 Counter 组件的代码,调用js函数:

@page "/counter"
@rendermode InteractiveAuto
@inject IJSRuntime JSRuntime

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>
<h2>@subMessage</h2>
<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary"  @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;
    private string subMessage = "";
    private IJSObjectReference? jsModule;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            jsModule = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Pages/Counter.razor.js");
        }    
    }
    private async Task IncrementCount()
    {
        currentCount++;
        await jsModule.InvokeVoidAsync("displayCount", currentCount);
        subMessage = await jsModule.InvokeAsync<string>("createMessage", currentCount);
    }
}
  • @inject IJSRuntime JSRuntime:注入 IJSRuntime 接口,用于与客户端 JavaScript 交互
  • IJSObjectReference? jsModule:保存对 JavaScript 模块的引用
  • JSRuntime.InvokeAsync
    <IJSObjectReference>
    :加载 JavaScript 模块并保存其引用

实际项目中,尽量不要使用js控制DOM,而是使用Blazor组件,因为两者可能起冲突。

原创作者: timefiles 转载于: https://www.cnblogs.com/timefiles/p/18338176
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值