《进击吧!Blazor!》第一章 3.页面制作

作者介绍

陈超超

Ant Design Blazor 项目贡献者 拥有十多年从业经验,长期基于.Net技术栈进行架构与开发产品的工作,Ant Design Blazor 项目贡献者,现就职于正泰集团

写专栏开头老规矩了,所以……先来段广告 《进击吧!Blazor!》是本人与张善友老师合作的Blazor零基础入门系列视频,此系列能让一个从未接触过Blazor的程序员掌握开发Blazor应用的能力。
视频地址: https://space.bilibili.com/483888821/channel/detail?cid=151273
演示代码: https://github.com/TimChen44/Blazor-ToDo
本系列文章是基于《进击吧!Blazor!》直播内容编写,升级.Net5,改进问题,讲解更全面。

更多学习资料:https://aka.ms/LearnBlazor

从这次分享开始我通过制作一个ToDo应用来介绍Balzor的开发。

准备工作

项目准备

  1. 打开上一次分享内容创建项目
  2. 2.修改wwwrootcssapp.css文件,只保留以下代码用于配置程序发生未捕获异常时的提示样式
#blazor-error-ui {     background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}
#blazor-error-ui .dismiss {     cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}
  1. 修改index.htm文件,移除对‘bootstrap’样式的引用,因为我们使用ant-design-blazor来做UI

引入ant-design-blazor包

✨ 特性
提炼自企业级中后台产品的交互语言和视觉风格。
开箱即用的高质量 Razor 组件,可在多种托管方式共享。
支持基于 WebAssembly 的客户端和基于 SignalR 的服务端 UI 事件交互。
支持渐进式 Web 应用(PWA)
使用 C# 构建,多范式静态语言带来高效的开发体验。
⚙️ 基于 .NET Standard 2.1/.NET 5,可直接引用丰富的 .NET 类库。 可与已有的 ASP.NET Core MVC、Razor Pages 项目无缝集成。

项目地址: https://github.com/ant-design-blazor/ant-design-blazor
文档地址: https://antblazor.com/

安装

  1. 用NuGet安装AntDesign包
Install-Package AntDesign -Version 0.5.3 
  1. Program.cs 中注册:
public static async Task Main(string[] args)
{
    //其他代码     builder.Services.AddAntDesign();
    await builder.Build().RunAsync();
} 
  1. wwwroot/index.html 中引入静态文件:

 
  1. _Imports.razor 中加入命名空间
@using AntDesign 
  1. 为了动态地显示弹出组件,需要在 App.razor 末尾添加一个 组件。
  

路由

在页面中切换,必定使用路由,我们先了解一下blazor的路由机制 App.razor 文件


    
        
    
    
        
            

Sorry, there's nothing at this address.

在上面第一行把当前项目的程序集赋值给了 Router 组件的 AppAssembly 属性,这样程序在启动时检索程序集中所有的页面用于路由,路由信息通过页面文件顶部的 @page 标记进行定义。还可以通过 AdditionalAssemblies 属性支持多个程序集。 Route里面有两个模板属性,分别是路由命中和未命中显示的内容、RouteView 组件用于显示路由的页面,这里从 Router 接收 routeData 以及任何所需的参数。 DefaultLayout="@typeof(MainLayout)" 定义了默认布局。

布局文件及菜单

编辑 Shared/MainLayout.razor 文件,制作程序的布局以及菜单。

@inherits LayoutComponentBase

    
        
        
            
                主页
            
            
                我的一天
            
            
                全部
            
        
    
    
        @Body
    


 

Layout页面布局组件

Layout组件帮助文档: https://antblazor.com/zh-CN/components/layout

Menu 菜单组件 Theme="MenuTheme.Dark"黑色主题

Menu组件帮助文档: https://antblazor.com/zh-CN/components/menu

MenuItem 菜单项组件 RouterLink="/" 路由地址 RouterMatch="NavLinkMatch.Prefix" 路由匹配模式,通过匹配 URL 来切换 active CSS 类,这有助于在导航菜单中显示那个页面是活动页。 NavLinkMatch.All:NavLink 在与当前整个 URL 匹配的情况下处于活动状态。 NavLinkMatch.Prefix(默认):NavLink 在与当前 URL 的任何前缀匹配的情况下处于活动状态。

@Body通过这个固定语法在布局中标记指定呈现内容的位置。

主页

编辑 Pages/Index.razor 文件

@page "/"
" 

这个主页左边是菜单,右边是内容,符合上一节布局格式,因为主页路由地址是/,所以默认就打开了。

@page "/" 页面路由地址

Result 结果组件,用于反馈一系列操作任务的处理结果,主页虽然是不反馈结果,不过当成ToDo应用门面效果还不错

Result组件帮助文档: https://antblazor.com/zh-CN/components/result

我的一天

一个用于显示和维护当天待办事项的界面 创建Pages/ToDay.razor文件

@page "/today"

 

启动后点击左边的“我的一天”菜单就可以导航到刚刚创建的页面,目前就只有一个页头。

@page "/today"设置当前页路由地址为/today

PageHeader 页头信息

PageHeader组件帮助文档: https://antblazor.com/zh-CN/components/pageheader

待办列表

ToDo的灵魂那就是待办列表了,那么三步走:先上代码,再看效果,最后讲解

@inject TaskServices TaskSvr

@foreach (var item in taskDtos)
{
    
        
@item.Title
@item.Description
} @code{ private List taskDtos = new List(); protected async override Task OnInitializedAsync() { taskDtos = await TaskSvr.LoadToDay(); await base.OnInitializedAsync(); } }

效果图

通过OnInitializedAsync方法中使用TaskSvr.LoadToDay()载入待办数据后存入taskDtos变量,最后通过@foreach遍历taskDtos集合,以Card组件作为容器,使用@item.Title@item.Description将数据单项绑定到界面显示。

@foreach (var item in taskDtos) { }这个和C#中的foreach功能相同 @标记可以把变量值单向绑定到页面中 @code{}razor语法中用于标记{}中可以插入c#代码

@inject TaskServices TaskSvr通过依赖注入TaskServices服务

关于依赖注入会在下一章节专题介绍,此处就不展开了

Card卡片容器 Bordered="true"显示卡片边框 Size="small"小尺寸卡片

Card组件帮助文档: https://antblazor.com/zh-CN/components/card

标记重要

有些待办肯定比其他待办更重要,所以增加一个标记重要的按钮,老规矩:先上代码,再看效果,最后讲解

@item.Description
private void OnStar(TaskDto task) { task.IsImportant = !task.IsImportant; }

div包裹一个Icon组件,然后在div上注册@onclick点击事件,当点击后会触发private void OnStar(TaskDto task)方法,并将当前项目item作为参数传入,方法中修改了TaskDtoIsImportant属性值,通过@(item.IsImportant ? "fill" : "outline")单向绑定,实现修改Icon组件的Theme样式在filloutline切换。

@()相比@标记,它可以在()括号中使用单行代码进行单向绑定。 @onclick事件绑定,除了onclick还有很多,详见ASP.NET Core Blazor事件处理

Icon语义化的矢量图形。 Type="star"图标名称

Icon组件帮助文档: https://antblazor.com/zh-CN/components/icon

计划时间

既然是待办,那么必然有一个计划开始时间PlanTime,以及一个截至时间Deadline,所以老规矩,三步走:先上代码,再看效果,最后讲解

@item.Description
@item.PlanTime.ToShortDateString()
@{ int? days = (int?)item.Deadline?.Subtract(DateTime.Now.Date).TotalDays; } 0 => "#ffd800", _ => "#ff0000" })"> @item.Deadline?.ToShortDateString()

上面显示计划日期PlanTime,下面显示Deadline,并通过与当前时间对比,根据时间差决定显示方式。

days switch { _ when days > 3 => "#ccc", _ when days > 0 => "#ffd800", _ => "#ff0000" }这是switch表达式写法,可以简化代码,如果使用if代码将比较臃肿,代码如下

@if (days > 3)
{
    
        @item.Deadline?.ToShortDateString()
    
}
else if (days > 0)
{
    
        @item.Deadline?.ToShortDateString()
    
}
else
{
    
        @item.Deadline?.ToShortDateString()
    
} 

待办详情

列表只适合查看待办概要,需要查看详情还需独立页面,所以我们做一个抽屉详情页,那么我们三步走 编辑ToDay.razor文件

@item.Title
@item.Description
1 2 3 4 5 [Inject] public DrawerService DrawerSrv { get; set; } async void OnCardClick(TaskDto task) { var options = new DrawerOptions() { Title = task.Title, Width = 450, }; await DrawerSrv.CreateDialogAsync(options, task); await InvokeAsync(StateHasChanged); }

新建TaskInfo.razor文件

@inherits DrawerTemplate