温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架

什么是Blazor

Blazor是一个使用.NET生成交互式客户端WebUI的框架:

  • 使用C#代替JavaScript来创建信息丰富的交互式UI。

  • 共享使用.NET编写的服务器端和客户端应用逻辑。

  • 将UI呈现为HTML和CSS,以支持众多浏览器,其中包括移动浏览器。

  • 与新式托管平台(如Docker)集成。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第1张图片

基于.Net Core提供客户端Web开发的优势

使用.NET进行客户端Web开发可提供以下优势:

  • 使用C#代替JavaScript来编写代码。

  • 利用现有的.NET库生态系统。

  • 在服务器和客户端之间共享应用逻辑。

  • 受益于.NET的性能、可靠性和安全性。

  • 在Windows、Linux和macOS上使用VisualStudio保持高效工作。

  • 以一组稳定、功能丰富且易用的通用语言、框架和工具为基础来进行生成。

Blazor组件

Blazor应用基于组件。Blazor中的组件是指UI元素,例如页面、对话框或数据输入窗体。

组件是内置到.NET程序集的.NET C#类,它们用于:

  • 定义灵活的UI呈现逻辑。

  • 处理用户事件。

  • 可以嵌套和重用。

  • 可作为Razor类库或NuGet包共享和分发。

组件类通常以Razor标记页(文件扩展名为.razor)的形式编写。Blazor中的组件有时被称为Razor组件。Razor是一种语法,用于将HTML标记与专为提高开发人员工作效率而设计的C#代码结合在一起。借助Razor,可使用Visual Studio中的IntelliSense编程支持在同一文件中的HTML标记与C#之间切换。Razor Pages和MVC也使用Razor。与基于请求/响应模型生成的Razor PagesMVC不同,组件专门用于处理客户端UI逻辑和构成。

Blazor使用UI构成的自然HTML标记。下面的Razor标记演示了一个组件(Dialog.razor),它显示一个对话框,并处理在用户选择按钮时发生的事件:

@Title

@ChildContent

@code { [Parameter] public RenderFragment ChildContent { get; set; } [Parameter] public string Title { get; set; } private void OnYes() { Console.WriteLine("Write to the console in C#! 'Yes' button selected."); } }

在上述示例中,OnYes是由按钮的onclick事件触发的C#方法。对话框的文本(ChildContent)和标题(Title)由在其UI中使用此组件的下述组件提供。

使用HTML标记将Dialog组件嵌入到另一个组件中。在以下示例中,Index组件(Pages/Index.razor)使用前面的Dialog组件。标记的Title属性向Dialog组件的Title属性传递标题的值。Dialog组件的文本(ChildContent)由

元素的内容设置。向Index组件添加Dialog组件后,Visual Studio中的IntelliSense可加快使用语法和参数补全进行开发的速度。

@page "/"

Hello, world!

Welcome to your new app.

Do you want to learn more about Blazor?

在浏览器中访问父级Index组件时,将呈现该对话框。当用户选择此按钮时,浏览器的开发人员工具控制台会显示由OnYes方法编写的消息:

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第2张图片

组件呈现为浏览器文档对象模型(DOM)的内存中表现形式,它被称为“呈现树”,用于以灵活高效的方式更新UI。

文档对象模型 (DOM) 是HTML和XML文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来。

一个web页面是一个文档。这个文档可以在浏览器窗口或作为HTML源码显示出来。但上述两个情况中都是同一份文档。文档对象模型(DOM)提供了对同一份文档的另一种表现,存储和操作的方式。DOM是web页面的完全的面向对象表述,它能够使用如 JavaScript等脚本语言进行修改。

Blazor Web Assembly

Blazor Web Assembly单页应用(SPA)框架,用于使用.NET生成交互式客户端Web应用。Blazor Web Assembly使用无插件或将代码重新编译为其他语言的开放式Web标准。Blazor Web Assembly适用于所有新式Web浏览器,包括移动浏览器。

通过WebAssembly(缩写为wasm),可在Web浏览器内运行.NET代码。Web Assembly是针对快速下载和最大执行速度优化的压缩字节码格式。Web Assembly是开放的Web标准,支持用于无插件的Web浏览器。

Web Assembly代码可通过JavaScript(称为JavaScript互操作性,通常简称为JavaScript互操作或JS互操作)访问浏览器的完整功能。通过浏览器中的Web Assembly执行的.NET代码在浏览器的JavaScript沙盒中运行,沙盒提供的保护可防御客户端计算机上的恶意操作。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第3张图片

Blazor Web Assembly应用生成并在浏览器中运行时:

  • C#代码文件和Razor文件将被编译为.NET程序集。

  • 该程序集和.NET运行时将被下载到浏览器。

  • BlazorWebAssembly启动.NET运行时,并配置运行时,以为应用加载程序集。BlazorWebAssembly运行时使用JavaScript互操作来处理DOM操作和浏览器API调用。

已发布应用的大小(其有效负载大小)是应用可用性的关键性能因素。大型应用需要相对较长的时间才能下载到浏览器,这会损害用户体验。Blazor Web Assembly优化有效负载大小,以缩短下载时间:

  • 在中间语言(IL)裁边器发布应用时,会从应用删除未使用的代码。

  • 压缩HTTP响应。

  • .NET运行时和程序集缓存在浏览器中。

Blazor托管模型

主要的Blazor托管模型在Web Assembly上的浏览器中运行客户端。将Blazor应用、其依赖项以及.NET运行时下载到浏览器。应用将在浏览器线程中直接执行。UI更新和事件处理在同一进程中进行。应用资产作为静态文件部署到可为客户端提供静态内容的Web服务器或服务中。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第4张图片

如果创建了Blazor Web Assembly应用进行部署,但没有后端ASP.NET Core应用来为其文件提供服务,那么该应用被称为独立Blazor Web Assembly应用。如果创建了应用进行部署,但没有后端应用来为其文件提供服务,那么该应用被称为托管的Blazor Web Assembly应用。托管的Blazor Web Assembly Client应用通常使用WebAPI调用或SignalR(结合使用ASP.NET Core SignalRBlazor)通过网络与后端Server应用交互。

blazor.webassembly.js脚本由框架和句柄提供:

  • 下载.NET运行时、应用和应用依赖项。

  • 初始化运行应用的运行时。

Blazor Web Assembly托管模型具有以下优点:

  • 没有.NET服务器端依赖项。应用下载到客户端后即可正常运行。

  • 可充分利用客户端资源和功能。

  • 工作可从服务器转移到客户端。

  • 无需ASP.NETCoreWeb服务器即可托管应用。无服务器部署方案可行,例如通过内容分发网络(CDN)为应用提供服务的方案。

Blazor Web Assembly托管模型具有以下局限性:

  • 应用仅可使用浏览器功能。

  • 需要可用的客户端硬件和软件(例如WebAssembly支持)。

  • 下载项大小较大,应用加载耗时较长。

  • .NET运行时和工具支持不够完善。例如,.NETStandard支持和调试方面存在限制。

在传统Web应用和单页应用(SPA)之间选择

Atwood 定律:任何能够用JavaScript编写的应用程序,最终必将用JavaScript编写。- Jeff Atwood

目前可通过两种通用方法来构建Web应用程序:在服务器上执行大部分应用程序逻辑的传统Web应用程序,以及在Web浏览器中执行大部分用户界面逻辑的单页应用程序(SPA),后者主要使用WebAPI与Web服务器通信。也可以将两种方法混合使用,最简单的方法是在更大型的传统Web应用程序中托管一个或多个丰富SPA类子应用程序。

何时使用传统Web应用程序:

  • 应用程序的客户端要求简单,甚至要求只读。

  • 应用程序需在不支持JavaScript的浏览器中工作。

  • 团队不熟悉JavaScriptTypeScript开发技术。

何时使用SPA:

  • 应用程序必须公开具有许多功能的丰富用户界面。

  • 团队熟悉JavaScriptTypeScriptBlazor Web Assembly开发。

  • 应用程序已为其他(内部或公共)客户端公开API。

此外,SPA框架还需要更强的体系结构和安全专业知识。相较于传统Web应用程序,SPA框架需要进行频繁的更新和使用新框架,因此改动更大。相较于传统Web应用,SPA应用程序在配置自动化生成和部署过程以及利用部署选项(如容器)方面的难度更大。

使用SPA方法改进用户体验时必须权衡这些注意事项。

传统Web应用程序、SPA或Blazor应用之间进行选择时要考虑的一些基本因素

因素 传统 Web 应用 单页面应用程序 Blazor 应用
需要团队熟悉 JavaScript/TypeScript 最低 必需 最低
支持不带脚本的浏览器 支持 不支持 支持
客户端应用程序行为极少 适合 不必要 可行
丰富而复杂的用户界面要求 受限 适合 适合

何时选择传统Web应用

应用程序的客户端要求简单,可能要求只读

对许多Web应用程序而言,其大部分用户的主要使用方式是只读。只读(或以读取为主)应用程序往往比那些维护和操作大量状态的应用程序简单得多。例如,搜索引擎可能由一个带有文本框的入口点和用于显示搜索结果的第二页组成。匿名用户可以轻松提出请求,并且很少需要使用客户端逻辑。同样,一般而言,博客或内容管理系统中面向公众的应用程序主要包含的内容与客户端行为关系不大。此类应用程序容易构建为基于服务器的传统Web应用程序,在Web服务器上执行逻辑,并呈现要在浏览器中显示的HTML。事实上,网站的每个独特页面都有自己的URL,搜索引擎可以将其存为书签和编入索引(默认设置,无需将此功能添加为应用程序的单独功能),这也是此类情况的一个明显优势。

应用程序需在不支持JavaScript的浏览器中工作

如需在有限或不支持JavaScript的浏览器中工作的Web应用程序,则应使用传统的Web应用工作流编写(或至少可以回退到此类行为)。SPA需要客户端JavaScript才能正常工作;如果没有客户端JavaScript,SPA不是好的选择。

团队不熟悉JavaScript或TypeScript开发技术

如果团队不熟悉JavaScriptTypeScript,但熟悉服务器端Web应用程序开发,那相较于SPA,他们交付传统Web应用的速度可能更快。除非以学习SPA编程为目的,或需要SPA提供用户体验,否则对已经熟悉构建传统Web应用的团队而言,选择传统Web应用的工作效率更高。

何时选择SPA

应用程序必须公开具有许多功能的丰富用户界面

SPA可支持丰富客户端功能,当用户执行操作或在应用的各区域间导航时无需重新加载页面。SPA很少需要重新加载整个页面,因此加载速度更快,可在后台提取数据,并且对单个用户操作的响应更快。SPA支持增量更新,可保存尚未完成的窗体或文档,而无需用户单击按钮提交窗体。SPA支持丰富的客户端行为,例如拖放,比传统应用程序更容易操作。可以将SPA设计为在断开连接的模式下运行,对客户端模型进行更新,并在重新建立连接后将更新最终同步回服务器。如果应用要求包括丰富的功能,且超出了典型HTML窗体提供的功能,则选择SPA样式应用程序。

通常,SPA需要实现内置于传统Web应用中的功能,例如在反映当前操作的地址栏中显示有意义的URL(并允许用户将此URL存为书签或对其进行深层链接以便返回此URL)。SPA还应允许用户使用浏览器的后退和前进按钮寻找用户意料之中的结果。

团队熟悉JavaScript和/或TypeScript开发

编写SPA需要熟悉JavaScriptTypeScript以及客户端编程技术和库。团队应有能力像使用Angular一样使用SPA框架编写新式JavaScript

参考-SPA框架

  • Angular:https://angular.io

  • React:https://reactjs.org/

  • Vue.js:https://vuejs.org/

应用程序已为其他(内部或公共)客户端公开API

如果已提供一个Web API供其他客户端使用,则相较于在服务器端窗体中复制逻辑,创建一个利用这些APISPA实现更加容易。用户与应用程序交互时,SPA广泛使用Web API来查询和更新数据。

何时选择Blazor

应用程序必须公开丰富用户界面

与基于JavaScript的SPA一样,Blazor应用程序可以支持丰富的客户端行为,而无需重载页面。这些应用程序对用户的响应更快,仅获取响应给定用户交互所需的数据(或HTML)。如果设计得当,可以将服务器端Blazor应用配置为以客户端Blazor应用的形式运行,只需在此功能受支持后对它进行稍加更改即可。

与使用JavaScript或TypeScript开发相比,团队更喜欢使用.NET开发

与使用JavaScriptTypeScript等客户端语言相比,许多使用.NET和Razor的开发人员的工作效率更高。由于已经使用.NET开发了应用程序的服务器端,因此,使用Blazor可以确保团队中的每名.NET开发人员都可以理解,并可能会生成应用程序前端的行为。

Blazor Server

Blazor将组件呈现逻辑从UI更新的应用方式中分离出来。Blazor ServerASP.NET Core应用中支持在服务器上托管Razor组件。可通过SignalR连接处理UI更新。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第5张图片

运行时停留在服务器上并处理:

  • 执行应用的C#代码。

  • 将UI事件从浏览器发送到服务器。

  • 将UI更新应用于服务器发送回的已呈现的组件。

Blazor Server用于与浏览器通信的连接还用于处理JavaScript互操作调用。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第6张图片

JavaScript互操作

对于需要第三方JavaScript库和访问浏览器API的应用,组件与JavaScript进行互操作。组件能够使用JavaScript能够使用的任何库或API。C#代码可调用到JavaScript代码,而JavaScript代码可调用到C#代码。

在ASP.NET Core Blazor中从.NET方法调用JavaScript函数

https://docs.microsoft.com/zh-cn/aspnet/core/blazor/call-javascript-from-dotnet?view=aspnetcore-5.0

从ASP.NET Core Blazor中的JavaScript函数调用.NET方法

https://docs.microsoft.com/zh-cn/aspnet/core/blazor/call-dotnet-from-javascript?view=aspnetcore-5.0

Blazor支持的平台

浏览者 Version
Apple Safari,包括 iOS 当前†
Google Chrome,包括 Android 当前†
Microsoft Edge 当前†
Mozilla Firefox 当前†

†最新指的是浏览器的最新版本。

Blazor模板选项

  • Blazor WebAssembly项目模板:blazorwasm

  • Blazor Server项目模板:blazorserver

创建我的第一个Blazor应用

1. 先准备".NET SDK (Software Development Kit)"环境。

如果之前没有安装的先安装这个SDK:

dotnet-sdk-5.0.202-win-x64.exe

如果已经安装过了,检查下当前版本:

dotnet --version

2. 根据Blazor项目模板创建应用

1) 命令行方式创建

dotnet new blazorserver -o BlazorApp --no-https

这里通过DOTNET-CLI执行新建项目的命令,使用的是blazorserver这个项目模板,输出项目文件夹为BlazorApp,给该项目设置为不需要HTTPS模式--no-https

如果要创建Blazor WebAssembly项目,这里将blazorserver改成blazorwasm即可。

dotnet new blazorwasm -o BlazorApp --no-https

2) Visual Studio方式创建

打开Visual Studio 2019最新版本,创建新项目,找到Blazor相关的项目模板。

  • Blazor Server应用

  • Blazor WebAssembly应用

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第7张图片

点击下一步,输入BlazorApp的项目名称,点击下一步进行创建。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第8张图片

目标框架,可以选.NET Core 3.1(长期支持),也可以选择.NET 5.0(当前),去掉勾选复选框配置HTTPS,点击创建即可。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第9张图片

创建成功之后,会自动打开项目解决方案。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第10张图片

3. 运行应用

1) 命令行方式创建

如果通过命令行方式创建,运行应用只需要执行:

dotnet watch run

通过DOTNET-CLIRun命令可以运行程序,这里添加watch参数的好处就是,等下如果改动了文件,会热重载,这样调试起来就很方便。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第11张图片

运行起来之后,会看到浏览器弹出应用首页。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第12张图片

如果要退出运行,只需要执行如下命令即可:

Ctrl + C

2) Visual Studio方式创建

Visual Studio里面运行就很简单了,直接点运行BlazorApp或者Ctrl + F5即可。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第13张图片

默认会打开一个终端控制台界面,用来显示Console日志。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第14张图片

运行起来之后,会看到浏览器弹出应用首页。

4. 项目结构

  • Program.cs 启用这个应用服务的入口节点。

  • Startup.cs 配置应用服务和中间件的地方。

  • App.razor 应用组件的根组件,也就是组件的入口位置。

  • BlazorApp/Pages 包含一些示例页面,也是页面目录。

  • BlazorApp.csproj 描述应用项目及其依赖关系。

5. 认识首页及组件

我们看到Pages/Index.razor这个主页。

@page "/"

Hello, world!

Welcome to your new app.

这里已经有了SurveyPrompt这样一个组件,同时它有一个入参Title可以定制。

6. 查看子组件计数器

打开Pages/Counter.razor,这是一个计数器的组件。

@page "/counter"

Counter

Current count: @currentCount

@code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }

我们可以从代码看到,顶部@page "/counter"实际上这个页面组件的目录,当我们切换到它时,路径也会变化。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第15张图片

每次点击Click me按钮的时候,就会从onclick事件去找到IncrementCount这个函数,在这个函数中,我们把currentCount做了加1,这时候,Current count的值会跟着刷新,可以看出只要绑定好了数据,它就会帮我们自动去更新界面显示了,还是很方便。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第16张图片

7. 在首页添加子组件计数器

打开Pages/Index.razor,我们在末尾追加Counter即可。

@page "/"

Hello, world!

Welcome to your new app.

这时候,我们查看页面就已经可以看到它了。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第17张图片

8. 修改组件添加属性并使用

接下来,我们打开Pages/Counter.razor,我们给这个组件添加一个参数属性IncrementAmount,默认值是1, 这样我们可以从外部传递值进来修改它,并且我们让currentCount不再是继续加1了,而是改成加IncrementAmount的值,这样我们就可以控制每次累加的幅度。

@page "/counter"

Counter

Current count: @currentCount

@code { private int currentCount = 0; [Parameter] public int IncrementAmount { get; set; } = 1; private void IncrementCount() { currentCount += IncrementAmount; } }

然后,我们回到Pages/Index.razor,在Counter组件上给他传递IncrementAmount的值进来。

@page "/"

Hello, world!

Welcome to your new app.

这时候,界面会自动重载,这时候,我们每次点击Click me,这个计时器组件就会加10了,哈哈,是不是很简单。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第18张图片

生成Blazor待办事项列表应用

1. 先准备".NET SDK (Software Development Kit)"环境。

如果之前没有安装的先安装这个SDK:

dotnet-sdk-5.0.202-win-x64.exe

如果已经安装过了,检查下当前版本:

dotnet --version

2. 创建待办事项列表Blazor应用

dotnet new blazorserver -o TodoList --no-https

通过DOTNET-CLI脚本的New命令,新建一个blazorserver项目模板,输出目录命名为TodoList,同时不需要HTTPS的支持。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第19张图片

3. 添加名为“Todo”的Blazor组件

cd TodoList

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第20张图片

先切换到TodoList项目文件夹中。

dotnet new razorcomponent -n Todo -o Pages

然后,通过DOTNET-CLI脚本的New命令,输出目录为Pages,新建名为Todorazorcomponent组件。

其中-n全称为--name,用来指定创建的名称,-o全称为--output,用来指定在这个目录进行创建。

Razor组件文件名要求首字母大写。打开Pages文件夹,确认Todo组件文件名以大写字母T开头。文件名应为Todo.razor

将在项目文件夹的Pages目录中,新建得到一个Todo.razor文件。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第21张图片

接下来,我们需要在Todo.razor文件顶部添加针对该文件组件的路由位置。

@page "/todo"

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第22张图片

4. 将“Todo”的Blazor组件添加到左侧导航

位于Shared文件夹的NavMenu.razor组件是控制左侧导航的,我们需要将“Todo”的Blazor组件添加到左侧导航中。

NavMenu.razor组件中,找到ul元素下的li节点,参考前面的例子,新建属于Todo组件的导航位置。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第23张图片

这里我们需要注意的几个关键点是,NavLinkhref需要填写组件的路由位置,其中span元素是菜单图标,紧跟着它的就是菜单名称,这里我们用ToDoList来作为菜单名称。

保存之后,我们通过执行run命令来运行,查看导航效果。

dotnet watch run

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第24张图片

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第25张图片

5. 添加“TodoItem”来存储待办事项数据。

这里一个小插曲就是为了更好的写出TodoItem.cs这个模型类,我遇到了两个不错的VSC插件,这里就顺带记录一下。

  • 名为C# Extensions的VSC插件,可以帮助我们支持在VSC中右键快速新建模型类和接口,有点类似VS中那种创建,至少帮你完成了当前命名空间的添加的活,所以值得推荐。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第26张图片

  • 名为C# XML Documentation Comments的VSC插件,平时我们在VS中写代码,习惯性的如果要添加函数或者属性的注释的话,上来就是///然后等待自动完成得到一串添加注释的注释体,这个插件就是来干这个事情的,效果还不错。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第27张图片

这两个插件,搜索C#这个关键词就可以看到了,基本上排在前面。

有了它们,我们创建TodoItem模型类就如虎添翼了。

在项目的Data文件夹中,我们右键,选择New C# Class,输入TodoItem,然后回车即可。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第28张图片

然后我们就自动完成,得到了一个基础的空的TodoItem.cs模型类,它的namespace都是已经处理好了,我觉得比手写强吧。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第29张图片

接下里,我们往TodoItem.cs模型类中添加两个属性(最好是走prop命令来新建),一个是Title来存储待办事项的标题,一个是IsDone来标记是否已完成该事项。

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第30张图片

接下来,为了将来更好的阅读这个模型,我们养成一个好习惯,给对应的模型和字段都添加好注释,这时候C# XML Documentation Comments这个VSC插件就要派上用场了,通过在所需要注释代码的开头位置,输入///然后回车即可。

namespace TodoList.Data
{
    /// 
    /// 待办事项
    /// 
    public class TodoItem
    {
        /// 
        /// 事项名称
        /// 
        /// 
        public string Title { get; set; }

        /// 
        /// 事项是否已完成
        /// 
        /// 
        public bool IsDone { get; set; }
    }
}

温故知新,.Net Core遇见Blazor(FluentUI),属于未来的SPA框架_第31张图片

参考

  • ASP.NET Core Blazor 简介

  • BlazorFluentUI

  • Blazor Webassembly Demo

  • DOM概述

  • 在传统 Web 应用和单页应用 (SPA) 之间选择

  • WebAssembly (abbreviated Wasm)

  • 从 ASP.NET Core Blazor 中的 JavaScript 函数调用 .NET 方法

  • 在 ASP.NET Core Blazor 中从 .NET 方法调用 JavaScript 函数

  • ASP.NET Core Blazor 托管模型

  • 用于 ASP.NET Core Blazor 的工具

  • Blazor Tutorial - Build your first Blazor app

  • 生成 Blazor 待办事项列表应用

  • C# Extensions - VS MarketPlace

  • C# XML Documentation Comments - VS MarketPlace

你可能感兴趣的:(python,java,javascript,linux,编程语言)