参考:
Blazor 教程 - 生成首个应用
https://dotnet.microsoft.com/zh-cn/learn/aspnet/blazor-tutorial/intro
Blazor基础知识:Visual Studio 2022 中的Blazor开发入门_vs2022 blazor webassembly-CSDN博客
https://blog.csdn.net/mzl87/article/details/135543830
[问题解决][edge]你现在无法访问 XXX.com,因为网站使用的是 HSTS。网络错误和攻击通常是暂时的,因此该页面以后可能会恢复正常。_因为网站使用的是 hsts。网络错误和攻击通常是暂时的,因此该页面以后可能会恢复正-CSDN博客
https://blog.csdn.net/ted_guangda/article/details/129010030
本地环境:win10, visual studio 2022 community
目录
- 创建项目
- 报错
- ResolvePackageAssets任务意外失败... NuGet unable to find fallback package folder xxx
- 启动后网页显示隐私错误 NET::ERR_CERT_INVALID
- 目录说明
- 详细说明
- 布局
- 网页
- index
- Counter
- FetchData
Blazor 使用 .NET 和 C# 构建全栈web应用,无需编写JavaScript。
创建项目
创建过程全部选默认,改动2处:
- 框架选了.Net 6.0
- 去掉了https配置(后面解释)
如果找不到上图的话装一下:
然后点击生成,运行:
报错
ResolvePackageAssets任务意外失败… NuGet unable to find fallback package folder xxx
这个很简单,去红线所指的位置新建文件夹即可。
启动后网页显示隐私错误 NET::ERR_CERT_INVALID
一个办法是直接在键盘输入 this is unsafe (不用打回车,就这几个字符就行)即可进入网页:
这个算个后门吧,不过因为我只是在测试,直接关掉https配置即可(前面创建项目时)。
搜解决办法的时候还有人说换火狐浏览器可以,我没有测试。我这里edge和chrome都不行。
目录说明
详细说明
布局
整个网页的布局写在Shared/MainLayout.razor,如下。其中:
@inherits LayoutComponentBase
表示将从LayoutComponentBase
类继承所有功能和属性,用户可以重写以定制注入导航栏、侧边栏等组件<NavMenu />
实际是自定义的blazor组件,参见Shared/NavMenurazor<article>
是一个HTML标签,通常包裹一个独立的内容块@Body
指明了主体内容在哪里。Pages下那些独立的页面会显示在这个位置- 相关的css写在同名.css文件中
@inherits LayoutComponentBase
<PageTitle>BlazorApp1</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
再看一下NavMenu元件。
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">BlazorApp1</a>
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</div>
</nav>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
前面html不用看,重点看一下这句:
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
这句表示:如果collapseNavMenu为true,则将NavMenuCssClass设置为"collapse";否则设为null。NavMenuCssClass是侧边栏主体部分的属性,在同名.css文件中是:
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.collapse {
/* Never collapse the sidebar for wide screens */
display: block;
}
}
也就是说,当窗口宽度大于641px时,通过设置.display: block; 实现了保持导航栏折叠按钮隐藏的效果,并确保侧边栏保持展开状态,以适应较宽屏幕设备的显示效果。
网页
index
红圈部分对应的是:Pages/Index.razor,内容是:
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
说明:
@
开头的属于c#代码,@page
指明了当前页的路径<PageTitle>
是blazor定义的一个组件,其实就是显示在标题栏的名字,也就是上图蓝圈的文字<SurveyPrompt>
是自定义的一个组件,放在Shared/SurveyPrompt.razor,内容是:<div class="alert alert-secondary mt-4"> <span class="oi oi-pencil me-2" aria-hidden="true"></span> <strong>@Title</strong> <span class="text-nowrap"> Please take our <a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2149017">brief survey</a> </span> and tell us what you think. </div> @code { // Demonstrates how a parent component can supply parameters [Parameter] public string? Title { get; set; } }
Counter
Counter页面多加了一个按钮,点击这个按钮,Current count: 后会更新点击次数:
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
说明:
@code
表示后面的花括号里包含的是c#代码- 页面上使用@ + 变量名就可以使用变量值
@onclick
直接使用@code
定义的函数
FetchData
这是一个带数据模型的页面,先看 FetchData.razor :
@page "/fetchdata"
<PageTitle>Weather forecast</PageTitle>
@using BlazorApp1.Data
@inject WeatherForecastService ForecastService
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from a service.</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()
{
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
}
说明:
@using BlazorApp1.Data
是使用这个命名空间// Data/WeatherForecast.cs namespace BlazorApp1.Data { public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string? Summary { get; set; } } }
inject
是注入服务// Data/ WeatherForecastService.cs namespace BlazorApp1.Data { public class WeatherForecastService { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate) { return Task.FromResult(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()); } } }
@if
中@表示是c#代码,直接用就行,后面@foreach
也是类似