(4/30)大家一起學blazor:component及路由居間

(4/30)大家一起學blazor:component及路由居間

由於筆者當初是用asp.net core api + blazor server,所以會以blazor server示範,日後研究完blazor webassembly會再將心得補上。

最后更新 2021/12/10 下午11:01
StrayaWorker
预计阅读 5 分钟
分类
Blazor
专题
一起學blazor系列
标签
.NET C# ASP.NET Core Blazor

由於筆者當初是用 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 元素內。

Index.razor和Counter.razor

两个Counter独立

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。

添加myClass到Counter按钮

接著我們看 fetchdata.razor,這裡看到了@using blazorserver.data,我們待會可以把這個 using 放進_import.razor,那麼@inject weatherforecastservice forecastservice 又是什麼呢?我們先看@code 區塊,看到這裡定義了 weatherforecast 數組類型的變量 forecasts,且用異步方法 oninitializedasync 調用了 forecastservice.getforecastasync(datetime.now),將結果回傳 forecasts,眼尖的人應該發現了最上面的 forecastservice 跟@code 區塊的 forecastservice 一模一樣。

FetchData.razor

我們點一下 getforecastasync()方法並按下 f12,可以看到這個方法回傳的就是 5 個隨機產生的天氣數據陣列,html 裡面有判斷 forecasts 是否為 null,不是的話就產生一個 table,裡面用 foreach 將 forecasts 的日期、攝氏、華氏及天氣狀態一一呈現出來。

Service生成数据及渲染

前面說過 blazor 只有一個網頁,其他內容都是一個個 component 組成的,每次觸發事件,server 或是 webassemlby 都會將相應 component 呈現在瀏覽器上,但 blazor 怎麼知道現在要呈現哪個 component 呢?

原因就是@page 指示词,这个指示词相当于传统的路由,可以看到 Index.razor 的@page 为"/",表示这是首页,Counter.razor 及 FetchData.razor 也有相应的@page 指示词。一个页面可以有多个@page 指示词,不过开头一定要有斜线且用双引号包起来,笔者曾想过建立 enum 集中管理不同 Component 的@page,可惜目前 Blazor 不支持这种做法。另外若两个 Component 用了相同的@page,编译阶段就会出现错误提示,所以也不用担心若有重复路由 Blazor 会怎么处理。

@page指示词

那麼左邊菜單的 home, counter, fetch data 頁面又是在哪裡定義的呢?打開 mainlayout.razor,可以看到 navmenu 元素,再打開 navmenu.razor,可以看到三個 navlink component,這些 component 會被 server 翻譯為瀏覽器認識的 a 元素,因此就算我們打開 dev tool,也只會看到 a 元素。

左侧菜单

左侧菜单在html呈现为a标签1

左侧菜单在html呈现为a标签2

回到 mainlayout.razor,可以看到@body 指示詞,這就是其他 component 會放置的地方,可以說是種 placeholder,再看 app.razor 裡面有 found 及 notfound 兩個 component,從字面看就知道,前者是當輸入的網址找到匹配的 component 則會進入這裡,後者則是找不到匹配的 component,可以看到兩者都用了 mainlayout。另外若有不同頁面要套用不同 layout,也可以自己定義。

@body

說到這裡,我們複習一下 blazor server 是怎麼走的,可以看到跟 angular 類似都是一層一層往下,管理較為方便。blazor webassemlby 跟 blazor server 的 index.html 跟_layout.cshtml 大致相等,以及缺少了 appsettings.json 文件,通常會將程式跟資料庫連接需要的連線字串放在這個文件,可證 blazor webassemlby 確實只是被動接收數據,而無法主動跟資料庫連接,筆者曾試過在這裡引用 ef core,也是無法讓 blazor webassemlby 接觸資料庫,在.net framework 的世界是用 xml 格式的 web.config,在.net core 則改用 json 格式的 appsettings.json。

引用: ASP NET Core blazor project structure

註:本文代碼通過 .net 6 + visual studio 2022 重構,可點擊原文連結與重構後代碼比較學習,謝謝閱讀,支持原作者

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2021/12/25

(29/30)大家一起學blazor:blazor單元測試

開發一個系統最無聊的過程大概就是解決bug了,尤其是那種嘗試對null 對象取值的錯誤(`object reference not set to an instance of an object.`),這應該是大部分人剛踏入編程領域最常碰到的問題,為了從枯燥的解決bug過程解脫,這篇就來居間`單元測試`。

继续阅读
同分类 / 同标签 2021/12/25

(28/30)大家一起學blazor:policy-based authorization

之前有說到`asp.net core identity` 使用的是基於`claim` 的驗證,其實`asp.net core identity` 有不同類型的授權方式,最簡單的`登錄授權`、`角色授權`、`claim 授權`,但上述幾種都是以一種方式實現:原則授權(`policy-based authorization`)。

继续阅读