Day 04 Compoent及路由介绍

由於笔者当初是用ASP.NET Core API + Blazor Server,所以会以Blazor Server示范,日後研究完Blazor WebAssembly会再将心得补上。

首先既然Component是可以重复利用的,我们在Index.razor放上两个Counter,启动专案(如果不想完整侦错,可以按ctrl+F5,就会启动不侦错模式,启动速度比较快,而且每次储存档案,Blazor都会侦测到,网页重整就可以载入新程序了),浏览器上两个Counter有各自的Click me按钮,分别点击後可以看到数字各别增加,代表是不同的Component,那这些数字又定义在哪里呢?

打开Counter.razor,最上面是@page指示词,这个稍後再说。再来是html跟一些C#程序,最後是@code区块,这就是Blazor的奇妙之处了,@code相当於一般网页JS做的事情诸如定义变数、实作方法、发送request到後端或是API,不过Blazor用C#编写,这里定义了一个私有变数currentCount,还有一个方法IncrementCount(),呼叫这方法的是Click me按钮,每一次点击按钮都会使currentCount+1,而呈现结果就在p元素内。
https://ithelp.ithome.com.tw/upload/images/20210904/20140893zC8Ab7zL3B.pnghttps://ithelp.ithome.com.tw/upload/images/20210904/20140893RxvtLJKih4.pnghttps://ithelp.ithome.com.tw/upload/images/20210904/20140893n2Rmn1ZTGn.png

currentCount定义的方式跟画面呈现就是一种模型系结(model binding),意思是资料跟画面有绑定关系,.NET Framework的View的@model或是@Viewbag,Angular的[(ngModel)]也是同理,都是要做到资料流到画面後,对画面操作可以影响资料的行为。

我们来定义另一个变数myClass,给这变数一些bootstrap的class,再把变数放在button的class里面,记住在html里面用到C#的程序必须以@开头,不然Blazor不知道要编译。重整页面可以看到按钮的样式变了,Blazor帮我们把myClass的值text-primary bg-warning放进button的class。
https://ithelp.ithome.com.tw/upload/images/20210904/20140893WToDxJQqhS.png
https://ithelp.ithome.com.tw/upload/images/20210904/20140893hzIyUelVOC.png

接着我们看FetchData.razor,因为萤幕不够长的关系,我将画面分成两部分截图,这里看到了@using BlazorServer.Data,我们待会可以把这个using放进_import.razor,那麽@inject WeatherForecastService ForecastService又是什麽呢?我们先看@code区块,看到这里定义了WeatherForecast阵列型别的变数forecasts,且用非同步方法OnInitializedAsync呼叫了ForecastService.GetForecastAsync(DateTime.Now),将结果回传forecasts,眼尖的人应该发现了最上面的ForecastService跟@code区块的ForecastService一模一样。
https://ithelp.ithome.com.tw/upload/images/20210904/20140893Gtju8sDW1S.pnghttps://ithelp.ithome.com.tw/upload/images/20210904/20140893QbBDGOAThv.png

我们点一下GetForecastAsync()方法并按下F12,可以看到这个方法回传的就是5个随机产生的天气资料阵列,html里面有判断forecasts是否为null,不是的话就产生一个table,里面用foreach将forecasts的日期、摄氏、华氏及天气状态一一呈现出来。
https://ithelp.ithome.com.tw/upload/images/20210904/20140893cDO2k2jRs5.png
https://ithelp.ithome.com.tw/upload/images/20210904/20140893h8vEey4Eca.png

前面说过Blazor只有一个网页,其他内容都是一个个Component组成的,每次触发事件,Server或是WebAssemlby都会将相应Component呈现在浏览器上,但Blazor怎麽知道现在要呈现哪个Component呢?

原因就是@page指示词,这个指示词相当於传统的路由,可以看到Index.razor的@page 为"/",表示这是首页,Counter.razor及FetchData.razor也有相应的@page指示词。一个页面可以有复数个@page指示词,不过开头一定要有斜线且用双引号包起来,笔者曾想过建立enum集中管理不同Component的@page,可惜目前Blazor不支援这种做法。另外若两个Component用了相同的@page,编译阶段就会出现错误讯息,所以也不用担心若有重复路由Blazor会怎麽处理。
https://ithelp.ithome.com.tw/upload/images/20210904/201408930G4rmcFsOG.pnghttps://ithelp.ithome.com.tw/upload/images/20210904/201408932WhWUHm43v.pnghttps://ithelp.ithome.com.tw/upload/images/20210904/20140893nct2VJJb6b.png

那麽左边菜单的Home, Counter, Fetch data页面又是在哪里定义的呢?打开MainLayout.razor,可以看到NavMenu元素,再打开NavMenu.razor,可以看到三个NavLink Component,这些Component会被Server翻译为浏览器认识的a元素,因此就算我们打开Dev tool,也只会看到a元素。
https://ithelp.ithome.com.tw/upload/images/20210904/20140893HDNP6tr8xr.png
https://ithelp.ithome.com.tw/upload/images/20210904/20140893RfF6ygIgcr.pnghttps://ithelp.ithome.com.tw/upload/images/20210904/20140893lp10tcmkRe.png
https://ithelp.ithome.com.tw/upload/images/20210904/20140893Tb1L5tDF9S.png

回到MainLayout.razor,可以看到@Body指示词,这就是其他Component会放置的地方,可以说是种placeholder,再看App.razor里面有Found及NotFound两个Component,从字面看就知道,前者是当输入的网址找到匹配的Component则会进入这里,後者则是找不到匹配的Component,可以看到两者都用了MainLayout。另外若有不同页面要套用不同Layout,也可以自己定义。
https://ithelp.ithome.com.tw/upload/images/20210904/20140893y5OLwY4IVX.png
https://ithelp.ithome.com.tw/upload/images/20210904/20140893xY5cRJ0Rxz.png

说到这里,我们复习一下Blazor Server是怎麽走的,可以看到跟Angular类似都是一层一层往下,管理较为方便。Blazor WebAssemlby跟Blazor Server差在Startup.cs的事情被Program.cs做了,以及_Host.cshtml跟index.html大致相等,以及缺少了appsettings.json档案,通常会将程序跟资料库沟通需要的连线字串放在这个档案,可证Blazor WebAssemlby确实只是被动接收资料,而无法主动跟资料库沟通,笔者曾试过在这里引用EF Core,也是无法让Blazor WebAssemlby接触资料库,在.NET Framework的世界是用XML格式的web.config,在.NET Core则改用JSON格式的appsettings.json。
https://ithelp.ithome.com.tw/upload/images/20210904/20140893NUK5XL9wLA.png

Ref: ASP NET Core blazor project structure


<<:  Day4 JavaScript 变量

>>:  从零开始学3D游戏开发:程序基础 Part.1 变数

[MIT-6.S081-2020] OS课程----Xv6作业系统的环境架设

前言 哈罗大家好,6.S081是麻省理工的一门作业系统的课程,小弟我在寒假时有听说这们课程很厉害,但...

Day 15 - React: setState 计数器之二

今天一口气练习 Hooks 跟第二种计数器写法。 先来用我的破英文翻译一下,现在的 React 允许...

# Day 26 Page migration (一)

文件 原文文件:Page migration 翻译: .. _page_migration: ===...

Day 08: Python额外知识小补充

Python额外知识 确认变数型别 Number = 1000 print(type(Number)...

Day05 - this&Object Prototypes Ch3 Objects - Contents - Property Descriptors 开头

我们已经知道 Object.getOwnPropertyDescriptor() 可以取得特定属性的...