天天看點

跟進 .NET 8 Blazor 之 ReuseTabs 支援 Query 屬性綁定

作者:opendotnet

ASP.NET 團隊和社群在 .NET 8 繼續全力投入 Blazor,為它帶來了非常多的新特性,特别是在服務端渲染(SSR)方面,一定程度解決之前 WASM 加載慢,Server 性能不理想等局限性,也跟原來的 MVC,Razor Pages 架構在底層完成了統一。

AntDesign Blazor 作為 Blazor 最受歡迎的開源元件庫之一,自然也會繼續佛系跟進。本篇主要介紹第一個在 AntDesign Blazor 上應用的 .NET 8 新特性——

CascadingModelBinder

,我利用它實作了 ReuseTabs 自 2021 年釋出兩年後,一直未支援的 Query String 屬性綁定。

ReuseTabs 是 AntDesign Blazor 在 2021 年 7 月增加的元件,也是 Blazor 目前唯一真正實作路由複用的元件。它隻需在 App.razor 增加 RouteData 級聯值,就可以在任何 Blazor 項目中獨立使用(其文檔上的例子就是在官方模闆上使用的),不依賴菜單配置就能夠主動識别路由,渲染頁面元件,并保持每個 Tab 頁面的狀态切換不會丢失。不像其他元件庫的實作,隻能在他們指定的配套模闆上才能使用…

回顧:Ant Design Blazor 元件庫的路由複用多标簽頁介紹,不過後來使用方式已經簡化了,最新的使用方法需要看 Github 上的文檔。

它的實作原理也很簡單,是通過級聯的 RouteData 值,擷取需要展示的元件類型以及要綁定頁面元件的屬性值,再動态渲染元件的。但是因為在 .NET 6 加入的 Query string 屬性值綁定實作是在 RouteView 内部利用一個内部靜态方法來解析 QueryString 并傳給頁面元件的,ReuseTabs 想要支援得把代碼都抄一份。當時就覺得這樣的設計很有局限(後來就懶得了)。

直到在前段時間 .NET 官方部落格中釋出的文章 ASP.NET Core 在 .NET 8 Preview 6 中的更新[1],裡面提到了一個特性,級聯 query string 值到 Blazor 元件,意思是不再讓 Query string 值綁定局限于頁面元件了,我就像這下 ReuseTabs 缺失了兩年的功能,有希望填補了。

跟進 .NET 8 Blazor 之 ReuseTabs 支援 Query 屬性綁定

Cascade query string values to Blazor components - .NET Blog

于是就有了今天要介紹的内容。

為了尋找官方是怎麼實作的,把 aspnetcore 倉庫源碼切換到 .NET 6 Preivew 6 的 tag 上,找到 RouteView 的源碼在RouteView.cs 中的 RenderPageWithParameters 方法[2],就是用于渲染頁面元件的。

跟進 .NET 8 Blazor 之 ReuseTabs 支援 Query 屬性綁定

RouteView

于是追溯這個檔案的曆史記錄,找到在這個支援服務端靜态渲染表單的 PR#47716[3] 加入了 CascadingModelBinder,這樣就可以從 Http 請求中擷取送出的 FormData 綁定到元件中标記了 SupplyParameterFromForm 特性的模型上。

跟進 .NET 8 Blazor 之 ReuseTabs 支援 Query 屬性綁定

RouteView CascadingModelBinder

接着,在 PR #48554[4] 中使 SupplyParameterFromQuery 也能夠通過 CascadingModelBinder 傳遞了,然後把上文提到的 RouteView 中的内部類 QueryParameterValueSupplier 相關代碼[5]删掉了。

跟進 .NET 8 Blazor 之 ReuseTabs 支援 Query 屬性綁定

RouteView delete QueryParameterValueSupplier

這簡直正中眉心,馬上我就把 RouteView 中的這段代碼複制到 ReuseTabs 中了,PRhttps://github.com/ant-design-blazor/ant-design-blazor/pull/3377[6],完美!

跟進 .NET 8 Blazor 之 ReuseTabs 支援 Query 屬性綁定

Ant Design Blazor PR 3377

最終效果:

跟進 .NET 8 Blazor 之 ReuseTabs 支援 Query 屬性綁定

開心之餘,我尋思着就算是抄,也不能抄的不明不白吧,于是就順便調查了一下 CascadingModelBinder 是怎麼傳遞級聯值的。簡單一句就是 Blazor 建立了 CascadingModelBinder 元件和 CascadingModelBindingProvider 提供者來抽象和統一了級聯傳值方法。沒想到官方部落格中平淡的兩句話介紹背後有這麼大的改動。詳情請關注我後面文章,另作介紹。

參考資料

[1]

ASP.NET Core 在 .NET 8 Preview 6 中的更新: https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-6/?WT.mc_id=DT-MVP-5003987#cascade-query-string-values-to-blazor-components

[2]

RouteView.cs 中的 RenderPageWithParameters 方法: https://github.com/dotnet/aspnetcore/blob/v8.0.0-preview.6.23329.11/src/Components/Components/src/RouteView.cs#L90

[3]

#47716: https://github.com/dotnet/aspnetcore/pull/47716/files#diff-c9ceeb487f25fa6e4e20bbc8eb15b597b014d77d3f464c51fd36d37e0365b96aR80-R84

[4]

#48554: https://github.com/dotnet/aspnetcore/pull/48554

[5]

内部類 QueryParameterValueSupplier 相關代碼: https://github.com/dotnet/aspnetcore/commit/883f06cbf5bfa9d82ef797c09fbcb6af7cbb1536#diff-c9ceeb487f25fa6e4e20bbc8eb15b597b014d77d3f464c51fd36d37e0365b96a

[6]

https://github.com/ant-design-blazor/ant-design-blazor/pull/3377: #3377

繼續閱讀