Blazor SPA 的本质是什么以及服务器端渲染如何与 Blazor 的新 Web 应用程序配合使用

Blazor 通常被称为单页应用程序 (SPA) 框架。当我第一次开始使用 Blazor 时,我对 SPA 的含义、组件如何为 SPA 架构做出贡献以及所有这些如何与交互性联系在一起感到困惑。

今天,我将解答大家可能关心的三个问题:

  1. 什么是 SPA?
  2. 了解所有新的“Blazor Web App”模板。
  3. 是什么使 Blazor 成为 SPA 应用程序?

什么是 SPA?

图 1 显示了传统的 Web 应用程序如何处理用户请求,它通常涉及用户为每个新页面向服务器发出请求。

例如,向服务器发送对“www.facebook.com/home.html”这样的主页的请求,服务器处理该请求然后返回主页。而当用户导航到个人资料页面时,将发出另一个对“www.facebook.com/profile.html”的请求,服务器现在将返回个人资料页面。

每次交互都会导致整个页面重新加载。


图 1:传统 Web 应用架构

现在让我们看看 SPA 应用程序是如何工作的,

用户体验保持不变。然而,在服务器上,我们不再提供完整的网页,而是使用组件。这是因为 Blazor 是一个基于组件的单页应用程序。

您可能想知道,哪个单页?在图 2 所示的架构中,App.razor是所有用户请求定向到的网页。服务器加载此单页并将其替换为请求的组件。

例如,当用户请求主页时,App.razor 会加载Home.razor组件。同样,当用户请求个人资料页面时,服务器首先加载App.razor,然后再加载 Profile.razor。

如下所示,Profile组件有附加组件, UserInfo.razor和UserOrders.razor。这称为组件层次结构。


图 2:基于 Blazor SPA 组件的架构

相比之下,SPA 会加载单个页面,并在用户与应用交互时动态更新内容。这是通过动态加载组件来实现的,无需完全重新加载,从而带来更流畅的用户体验。

例如,在 YouTube 上,当你给视频添加评论时,评论部分会更新,而不会中断视频播放。这是因为评论部分是一个单独的组件,可以独立刷新,而不会影响其他部分。

创建 Blazor Web 应用

让我们通过创建 Blazor Web 应用程序来看一下它的实际效果。

  • 打开 Visual Studio 并选择 Blazor Web App 模板。


图 3:创建新的 Blazor Web 应用程序

  • 为您的应用命名并选择一个位置。


图 4:Blazor 中的项目配置

  • 选择“.NET 8” 作为框架。将“身份验证类型”设置为“无” ,并为“交互式渲染模式”选择“无”,以确保我们使用 Blazor SSR(静态服务器端渲染)。忽略“交互位置选项”,因为当为交互式渲染模式选择“无” 时,它不适用。最后,点击创建按钮。


图 5:Blazor Web 应用的附加信息

在解决方案资源管理器中,您将看到类似以下的结构:


图 6:Blazor Web 应用文件夹结构

理解代码

首先,让我向您展示您请求的页面在 Blazor 应用中加载的顺序。请注意数字,因为它们代表控制流。我们将在下面详细介绍每个文件,解释它们在此过程中的作用。


图 7:Blazor Web 应用中的控制流

让我们回顾一下早期的 C# 时代。众所周知,Program.cs是 C# 应用程序的入口点,对于 Blazor 来说,它遵循同样的原则

以下是 Program.cs 中的代码

using MyFirstBlazorWebApp.Components;var builder = WebApplication.CreateBuilder(args);// Add services to the container.
builder.Services.AddRazorComponents();var app = builder.Build();// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{app.UseExceptionHandler("/Error", createScopeForErrors: true);// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.app.UseHsts();
}app.UseHttpsRedirection();app.UseStaticFiles();
app.UseAntiforgery();app.MapRazorComponents<App>();app.Run();

代码片段 1:Program.cs

该文件处理用户发出的 HTTP 请求(例如,/index、/profile),如上面的架构图所示。

从第 18行到第 21行,你可以看到专门用于管理这些 HTTP 请求的方法。在第 23行,HTTP 请求被映射到名为App 的组件。

你可能会问,这是什么应用程序?

这与我们架构图(图 2)中显示的App.razor相同,这意味着所有请求在到达App.razor之前都会流经Program.cs。

让我们探索一下 App.razor 中的内容

<!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="MyFirstBlazorWebApp.styles.css" /><link rel="icon" type="image/png" href="favicon.png" /><HeadOutlet />
</head><body><Routes /><script src="_framework/blazor.web.js"></script>
</body></html>

代码片段 2:App.razor

这主要是标准 HTML,但有一个明显的区别:在第 16行,它调用名为的组件。

组件的作用是定位并加载特定的请求组件。例如,当用户请求主页时,它会找到Home.razor,而当用户请求个人资料页面时,它会找到Profile.razor并替换它。

那么 组件包含什么?

<Router AppAssembly="typeof(Program).Assembly"><Found Context="routeData"><RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" /><FocusOnNavigate RouteData="routeData" Selector="h1" /></Found>
</Router>

代码片段 3:Routes.razor

Router组件负责定位请求的组件并将其应用到第 3 行的MainLayout。路由完成后,Router 组件会更新MainLayout。

让我们打开 MainLayout.razor

@inherits LayoutComponentBase<div class="page"><div class="sidebar"><NavMenu /></div><main><div class="top-row px-4"><a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a></div><article class="content px-4">@Body</article></main>
</div>

代码片段 4:MainLayout.razor

注意第 14行,其中有一个“@Body” 占位符。这是插入请求组件的位置。因此,当 请求“Home.razor”时,其 HTML 内容将替换“@Body” 占位符,整个页面将通过路由器发送回浏览器中显示。

提示:其余代码代表您的 Web 应用的布局。如果您想为您的应用定义一个带有侧边栏、页眉、页脚和动态中心内容的自定义布局,这里就是您要做的。

不要太担心这些理论;让我们继续运行该应用程序,看看它的实际作用。


图 8:加载 Blazor 应用程序

在这里,您可以看到左侧的侧边栏(来自MainLayout.razor的第 4 个代码片段)和中间加载的主体内容。当 Web 应用首次运行时,它会重定向到根 URL (/) 。在我们的演示应用中,这由Home.razor表示,如图 7 中的项目 5 所示。

它看起来是这样的:

@page "/"<PageTitle>Home</PageTitle><h1>Hello, world!</h1>Welcome to your new app.

代码片段 5:Home.razor

现在,让我们更改用户请求并点击侧边栏中的天气按钮。您会注意到 URL 更改为"https://localhost:7106/weather"。

此时,App.razor将要求Router查找具有“@page /weather”路由的组件,并将其替换到 body 部分。为此,我们有一个Weather.razor组件,其中包含一些静态数据。

@page "/weather"
@attribute [StreamRendering]<PageTitle>Weather</PageTitle><h1>Weather</h1><p>This component demonstrates showing data.</p>@if (forecasts == null)
{<p><em>Loading...</em></p>
}
else
{<table class="table"><thead><tr><th>Date</th><th>Temp. (C)</th><th>Temp. (F)</th><th>Summary</th></tr></thead><tbody>@foreach (var forecast in forecasts){<tr><td>@forecast.Date.ToShortDateString()</td><td>@forecast.TemperatureC</td><td>@forecast.TemperatureF</td><td>@forecast.Summary</td></tr>}</tbody></table>
}@code {private WeatherForecast[]? forecasts;protected override async Task OnInitializedAsync(){// Simulate asynchronous loading to demonstrate streaming renderingawait Task.Delay(500);var startDate = DateOnly.FromDateTime(DateTime.Now);var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast{Date = startDate.AddDays(index),TemperatureC = Random.Shared.Next(-20, 55),Summary = summaries[Random.Shared.Next(summaries.Length)]}).ToArray();}private class WeatherForecast{public DateOnly Date { get; set; }public int TemperatureC { get; set; }public string? Summary { get; set; }public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);}
}

代码片段 6:Weather.razor

如您所见,这个Weather.razor组件现在位于中心,取代了Home.razor组件。


图片 9:天气页面加载

让我检查一下该元素并向您展示它如何在浏览器中显示为单个页面。


图 10:检查天气页面上的元素

中间是 Weather.razor的代码,上方是几个

,其中一个带有类“page”,内部带有类“sidebar”。这些来自 MainLayout.razor的第 3行和第 4行。因此,最终,所有这些组件组合在一起形成一个页面。

看看下面的 GIF。请注意,单击主页和天气页面只会替换正文。


GIF 1:在主页和天气页面之间导航

各位,所有关于SSR(服务器端渲染)的讨论都归结为这一点。它是一种 Blazor 托管模型,应用程序在服务器上运行,UI 更新通过SignalR 连接发送到客户端。这正是我们在本文中看到的:每次用户请求网页时,它都会在服务器上生成并发送到客户端,然后在浏览器中呈现。

##结论
Blazor 提供了一个强大的框架,用于使用基于组件的架构构建单页应用程序。您可以创建高度交互的 Web 应用程序。关键在于了解 Blazor 如何处理用户请求并动态更新内容而无需重新加载整个页面,从而提供流畅的用户体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/42226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【高中数学/基本不等式】当x是正实数时,求函数f(x)=x/(1+x^2)的最大值?

【问题】 当x是正实数时&#xff0c;求函数f(x)x/(1x^2)的最大值&#xff1f; 【解答】 解&#xff1a; f(x)x/(1x^2)1/(x1/x))<1/2倍根号下(x*1/x)1/2 所以函数在[0,∞)的区域最大值为0.5 【函数图像】 f(x)x/(1x^2)是奇函数&#xff0c;没有断点&#xff0c;是可以…

文心一言最常用的20条指令及指令说明,含增强指令

下面是20条文心一言的指令及其说明&#xff0c;每条指令尽量简洁明了&#xff0c;以便在有限的字数内提供尽可能多的信息。以下是这些指令及其说明&#xff1a; 1. 查询天气 指令&#xff1a;今天北京的天气怎么样&#xff1f;说明&#xff1a;此指令用于查询特定城市&#xf…

HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…

Redis高级篇之最佳实践

Redis高级篇之最佳实践 今日内容 Redis键值设计批处理优化服务端优化集群最佳实践 1、Redis键值设计 1.1、优雅的key结构 Redis的Key虽然可以自定义&#xff0c;但最好遵循下面的几个最佳实践约定&#xff1a; 遵循基本格式&#xff1a;[业务名称]:[数据名]:[id]长度不超过…

PCIe 规范核心知识线介绍

0&#xff0c;总体Topology x86 处理器系统中 PCIe的拓扑结构&#xff1a; PCIe Switch的总体结构 1&#xff0c;PCIe 枚举 BIOS 负责枚举与分派配置设备的 BusID[7:0] : DeviceID[4:0] : FunctionID[2:0]; cpu先识别 Host-PCI-Bridge&#xff0c;其下是Bus0&#xff1b; 在…

树莓派学习笔记18:IIC驱动_PCA9685(16路舵机驱动模块)误发

今日继续学习树莓派4B 4G:(Raspberry Pi,简称RPi或RasPi) 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: ​ Python 版本3.7.3: ​ IIC驱动_PCA9685(16路舵机驱动模块) 文章提供测试代码讲解,整体代码贴出、测试效果图 目录 开启树莓…

什么是 HTTP POST 请求?初学者指南与示范

在现代网络开发领域&#xff0c;理解并应用 HTTP 请求 方法是基本的要求&#xff0c;其中 "POST" 方法扮演着关键角色。 理解 POST 方法 POST 方法属于 HTTP 协议的一部分&#xff0c;主旨在于向服务器发送数据以执行资源的创建或更新。它与 GET 方法区分开来&…

尚硅谷 一 JS简介

一 JS简介 1.1 JS起源 Javascript是一种由Netscape(网景)的LiveScript发展而来的原型化继承的面向对象的动态类型的区分大小写的客户端脚本语言&#xff0c;主要目的是为了解决服务器端语言&#xff0c;遗留的速度问题&#xff0c;为客户提供更流畅的浏览效果。当时服务端需要…

vue3+vue-router+vite 实现动态路由

文章中出现的代码是演示版本&#xff0c;仅供参考&#xff0c;实际的业务需求会更加复杂 什么是动态路由 什么场景会用到动态路由 举一个最常见的例子&#xff0c;比如说我们要开发一个后台管理系统&#xff0c;一般来说后台管理系统都会分角色登录&#xff0c;这个时候也就涉…

第4章 课程发布:模块需求分析,课程预览(模板引擎 静态页面),课程审核,课程发布(分布式事务,页面静态化:熔断降级),课程搜索(es索引)

1 模块需求分析 1.1 模块介绍 课程信息编辑完毕即可发布课程&#xff0c;发布课程相当于一个确认操作&#xff0c;课程发布后学习者在网站可以搜索到课程&#xff0c;然后查看课程的详细信息&#xff0c;进一步选课、支付、在线学习。 下边是课程编辑与发布的整体流程&#…

一.2.(1)双极型晶体三极管的结构、工作原理、特性曲线及主要参数

1.双极型晶体三极管的结构 学会区分P管和N管&#xff0c;会绘制符号 2.工作原理 无论是PNP 还是NPN&#xff0c;本质上放大时&#xff0c;都是发射结正偏&#xff0c;集电极反偏。&#xff08;可以简单理解为pn为二极管&#xff0c;每个三极管都有两个二极管&#xff09; 其中电…

前端面试题22(js中sort常见的用法)

JavaScript 的 sort() 方法是数组的一个非常强大的功能&#xff0c;用于对数组的元素进行排序。这个方法直接修改原数组&#xff0c;并返回排序后的数组。sort() 的默认行为是将数组元素转换为字符串&#xff0c;然后按照字符串的 Unicode 字典顺序进行排序。这意味着如果你试图…

Linux内存管理--系列文章柒——硬件架构

一、引子 之前文章讲解的是系统的虚拟内存&#xff0c;本章讲述这些硬件的架构和系统怎样统一管理这些硬件的。 二、物理内存模型 物理内存模型描述了计算机系统中的物理内存如何由操作系统组织和管理。它定义了物理内存如何划分为单元&#xff0c;如何寻址这些单元以及如何…

powershell美化工具Oh My Posh安装教程

1. 安装Oh My Posh 进入Oh My Posh官网&#xff0c;可根据不同平台进行下载 windows下可以直接在微软商店下载 2. 安装Nerd Fonts字体 进入Nerd Fonts官网&#xff0c;选择自己喜欢的字体下载解压后&#xff0c;全选所有文件&#xff0c;右键选择安装即可&#xff08;忽略LICEN…

ARM_Linux驱动开发——字符设备驱动开发(上)

目录 一、Linux驱动开发思维 二、Linux驱动开发分类 三、“ ARM_Linux驱动开发——字符设备驱动开发 ” 字符设备驱动简介 前言 在分享Linux驱动开发之前&#xff0c;我想带大家首先回顾一下裸机驱动开发和Linux驱动开发的区别。 1、运行环境和操作系统&#xff1a; 裸机驱…

Apache Seata 高可用部署实践

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Apache Seata 高可用部署实践 Seata 高可用部署实践 使用配置中心和数据库来实现 Seata 的高…

使用Spring Boot和自定义缓存注解优化应用性能

在现代应用开发中&#xff0c;缓存是提高系统性能和响应速度的关键技术之一。Spring Boot提供了强大的缓存支持&#xff0c;但有时我们需要更灵活的缓存控制。本文将介绍如何使用Spring Boot和自定义缓存注解来优化应用性能。 1. 为什么需要自定义缓存注解&#xff1f; Sprin…

AI算力革命:GPU租赁与算力市场的未来趋势

在数字化和智能化的时代背景下&#xff0c;人工智能&#xff08;AI&#xff09;的快速发展已成为全球科技领域的焦点。AI算力作为支撑其发展的关键因素&#xff0c;正以前所未有的速度改变着我们的生活和工作方式。其中&#xff0c;GPU租赁模式的兴起&#xff0c;不仅解决了AI算…

ASP.NET Web应用中的 Razor Pages/MVC/Web API/Blazor

如果希望使用ASP.NET Core创建新的 Web 应用程序&#xff0c;应该选择哪种方法&#xff1f;Razor Pages还是 MVC&#xff08;模型-视图-控制器&#xff09;&#xff0c;又或者使用Web API Vue/React/......。 每种方法都有各自的优点和缺点。 什么是 MVC&#xff1f; 大多数服…

轻松设置:服务器域名配置全攻略

目录 前置条件 在阅读本篇内容之前&#xff0c;请先确保以下物料已准备好&#xff1a; 一台公网服务器&#xff0c;服务正常运行申请完成的域名&#xff0c;在对应域名服务商后台正常DNS解析域名备案完成可选条件&#xff1a;有https访问请求时&#xff0c;需要申请SSL证书 …