使用MASA?Blazor開發(fā)查詢表格頁
前言
大家好,我是開源項(xiàng)目 MASA Blazor 主要開發(fā)者之一,如果你還不了解MASA Blazor,可以訪問我們的 官網(wǎng) 和博客 《初識(shí)MASA Blazor》 一探究竟。簡(jiǎn)單來說,MASA Blazor 是一個(gè)基于 Material Design 設(shè)計(jì)語言的 Blazor 組件庫(kù),dotNET開發(fā)者只需或者甚至不需要懂得 javascript 就能開發(fā)一個(gè)企業(yè)級(jí)中后臺(tái)系統(tǒng)。
我這次分享的主題是《使用MASA Blazor開發(fā)一個(gè)標(biāo)準(zhǔn)的查詢表格頁》,我會(huì)先從創(chuàng)建項(xiàng)目開始手?jǐn)]一個(gè)沒有任何技巧的查詢表格頁,然后我會(huì)分享一些技巧和封裝的組件,實(shí)現(xiàn)快速開發(fā)。
手?jǐn)]查詢表格頁
創(chuàng)建應(yīng)用程序
關(guān)于如何安裝MASA Blazor模板,請(qǐng)移步 MASA.Blazor快速入門。
首先通過MASA Blazor模板默認(rèn)的Server項(xiàng)目,項(xiàng)目命名為 MasaBlazorStandardTablePage。
dotnet new --install MASA.Template dotnet new masab -o MasaBlazorStandardTablePage
通過CLI運(yùn)行應(yīng)用程序,或直接通過vs啟動(dòng)項(xiàng)目。
cd MasaBlazorStandardTablePage dotnet run
啟動(dòng)成功后切換到 Fetch data 頁面,此頁面展示了一個(gè)簡(jiǎn)單的使用了 MDataTable 的表格。

支持單個(gè)查詢條件和搜索
讓我們從最簡(jiǎn)單的單個(gè)條件查詢開始。
將隨機(jī)數(shù)據(jù)替換成模擬數(shù)據(jù)
修改 WeatherForecastService,將隨機(jī)數(shù)據(jù)替換成死數(shù)據(jù)以便支持查詢功能。下面的代碼更新了數(shù)據(jù)來源和 GetForecastAsync 查詢方法。
public class WeatherForecastService
{
private readonly List<WeatherForecast> _data = new()
{
new() { Date = DateTime.Now.AddDays(-1), TemperatureC = 23, Summary = "Freezing" },
new() { Date = DateTime.Now.AddDays(-1), TemperatureC = -10, Summary = "Bracing" },
new() { Date = DateTime.Now.AddDays(-1), TemperatureC = 37, Summary = "Chilly" },
new() { Date = DateTime.Now.AddDays(-2), TemperatureC = 29, Summary = "Cool" },
new() { Date = DateTime.Now.AddDays(-3), TemperatureC = 11, Summary = "Mild" },
new() { Date = DateTime.Now.AddDays(-4), TemperatureC = 35, Summary = "Warm" },
new() { Date = DateTime.Now.AddDays(-5), TemperatureC = 41, Summary = "Balmy" },
new() { Date = DateTime.Now.AddDays(-5), TemperatureC = -13, Summary = "Hot" },
new() { Date = DateTime.Now.AddDays(-6), TemperatureC = 23, Summary = "Sweltering" },
new() { Date = DateTime.Now.AddDays(-7), TemperatureC = 2, Summary = "Scorching" },
};
public Task<WeatherForecast[]> GetForecastAsync()
{
IEnumerable<WeatherForecast> res = _data.AsQueryable();
return Task.FromResult(res.ToArray());
}
}同時(shí)修改 FetchData.razor,因?yàn)?WeatherForecastService.GetForecastAsync() 刪除了 startDate 入?yún)ⅰ?/p>
protected override async Task OnInitializedAsync()
{
await Task.Delay(1000); // 模擬真實(shí)環(huán)境,觸發(fā)Loading效果
forecasts = await ForecastService.GetForecastAsync(); // here
}添加查詢輸入框和搜索按鈕
在 FetchData.razor 頁面中的 <p> 標(biāo)簽下添加以下代碼
<MRow Class="pb-3">
<MCol Cols="12">
<MTextField @bind-Value="summary"
Dense
HideDetails="@("auto")"
Label="Summary"
Outlined>
</MTextField>
</MCol>
<MCol Cols="12" Class="d-flex py-0 pb-3">
<MSpacer></MSpacer>
<MButton Color="primary" OnClick="OnSearch">搜索</MButton>
</MCol>
</MRow>
@code {
private string summary;
private async Task OnSearch()
{
forecasts = await ForecastService.GetForecastAsync(summary);
}
}Line 3,17
定義了一個(gè) string 類型的名為 summary 的變量,雙向綁定給了 MTextField 組件。MTextFiled 除了 @bind-Value 屬性用于設(shè)置雙向綁定,其他屬性的含義請(qǐng)閱讀 文檔。
Line 12
定義了一個(gè)搜索按鈕,用于觸發(fā)查詢。
修改 WeatherForecastService.GetForecastAsync 方法,增加 summary 入?yún)ⅲ⒅С植樵儭?/p>
public Task<WeatherForecast[]> GetForecastAsync(string? summary = null)
{
IEnumerable<WeatherForecast> res = _data.AsQueryable();
if (!string.IsNullOrEmpty(summary))
{
res = res.Where(item => item.Summary.Contains(summary));
}
return Task.FromResult(res.ToArray());
}
支持多個(gè)查詢條件和重置
現(xiàn)在讓我們?cè)偬砑右粋€(gè)高溫預(yù)警的選擇框來查詢不同高溫預(yù)警狀態(tài)的數(shù)據(jù)。
更新 WeatherForecastService 以支持根據(jù)高溫預(yù)警篩選數(shù)據(jù)
public Task<WeatherForecast[]> GetForecastAsync(string? summary = null, WarningSigns? warningSigns = null)
{
IEnumerable<WeatherForecast> res = _data.AsQueryable();
if (!string.IsNullOrEmpty(summary))
{
res = res.Where(item => item.Summary.Contains(summary));
}
if (warningSigns.HasValue)
{
res = warningSigns switch
{
WarningSigns.Yellow => res.Where(item => item.TemperatureC >= 35 && item.TemperatureC < 37),
WarningSigns.Orange => res.Where(item => item.TemperatureC >= 37 && item.TemperatureC < 39),
WarningSigns.Red => res.Where(item => item.TemperatureC >= 39),
_ => res
};
}
return Task.FromResult(res.ToArray());
}增加高溫預(yù)警選擇框
在 Data 目錄下添加名為 WarningSigns 的枚舉。
public enum WarningSigns
{
[Description("高溫黃色預(yù)警 35℃")]
Yellow = 1,
[Description("高溫橙色預(yù)警 37℃")]
Orange,
[Description("高溫紅色預(yù)警 39℃")]
Red
}引入 Masa.Utils.Enums 包,此包提供的 GetEnumObjectList 方法能輕松的將枚舉的 Description 和枚舉值用于 MSelect 組件的 Items。
dotnet add package Masa.Utils.Enums
更新 FetchData.razor。
<MRow Class="pb-3">
<MCol Cols="12" Sm="6">
<MTextField @bind-Value="@summary"
Label="Summary"
Dense
HideDetails="@("auto")"
Outlined>
</MTextField>
</MCol>
<MCol Cols="12" Sm="6">
<MSelect @bind-Value="warningSigns"
Items="@(Enum<WarningSigns>.GetEnumObjectList<WarningSigns>())"
ItemText="item => item.Name"
ItemValue="item => item.Value"
TValue="WarningSigns?"
TItem="EnumObject<WarningSigns>"
TItemValue="WarningSigns"
Label="高溫警告"
Clearable
Dense
HideDetails="@("auto")"
Outlined>
</MSelect>
</MCol>
<MCol Cols="12" Class="d-flex py-0 pb-3">
<MSpacer></MSpacer>
<MButton Class="mr-2" OnClick="OnReset">重置</MButton>
<MButton Color="primary" OnClick="OnSearch">搜索</MButton>
</MCol>
</MRow>
@code {
private WarningSigns? warningSigns;
private Task OnReset()
{
summary = null;
warningSigns = null;
return OnSearch();
}
private async Task OnSearch()
{
forecasts = await ForecastService.GetForecastAsync(summary, warningSigns);
}
}Line 2,10
通過設(shè)置 Sm="6" 可以讓屏幕尺寸大于768px時(shí)一行占兩個(gè) MCol ,實(shí)現(xiàn) MTextField 和 MSelect 并排顯示。
Line 11-23,33,44
第33行定義 warningSigns 變量用于接收 MSelect 選中的值,當(dāng)然也可以通過設(shè)置值更新 MSelect 選中的值,只要設(shè)置了 @bind-Value 雙向綁定就行,就像第11行那樣。第12行使用了 Masa.Utils.Enums 提供的方法,返回了一個(gè)包含Name(Description)和Value(枚舉值)的列表,賦值給了 MSelect.Items 。第44行將 warningSigns 的傳給查詢接口。
Line 27,35-40
此處定義了一個(gè)重置按鈕,用于清空所有查詢輸入框的內(nèi)容并刷新表格。

支持鍵入回車或選擇后觸發(fā)查詢
后來測(cè)試小姐姐說你這太難用了,回車不能觸發(fā)搜索,選擇完也不能觸發(fā)搜索。好吧好吧,我們現(xiàn)在加上。
鍵入回車后觸發(fā)
原理即捕捉 OnKeyDown 事件是否點(diǎn)擊了 Enter 鍵。
<MTextField @bind-Value="@summary"
OnKeyDown="HandleOnKeyDown"
Label="Summary"
Dense
HideDetails="@("auto")"
Outlined>
</MTextField>
@code {
private async Task HandleOnKeyDown(KeyboardEventArgs args)
{
if (args.Code == "Enter")
{
// 等待156毫秒,預(yù)防輸入的值在更新到變量之前按下Enter鍵
await Task.Delay(156);
await OnSearch();
}
}
}Line 2
將 HandleOnKeyDown 綁定到 MTextField 的 OnKeyDown 事件。
Line 10-17
通過判斷 KeyboardEventArgs 的 Code 值是否為 Enter 來觸發(fā)搜索。第14行等待156毫秒是為了等待 summary 的值已經(jīng)是輸入過后的值。
選擇后觸發(fā)查詢
<MSelect @bind-Value="warningSigns"
Items="@(Enum<WarningSigns>.GetEnumObjectList<WarningSigns>())"
ItemText="item => item.Name"
ItemValue="item => item.Value"
TValue="WarningSigns?"
TItem="EnumObject<WarningSigns>"
TItemValue="WarningSigns"
Label="高溫警告"
OnSelectedItemUpdate="OnSearch"
Clearable
Dense
HideDetails="@("auto")"
Outlined>
</MSelect>Line 9
當(dāng)選擇項(xiàng)更新時(shí)(OnSelectedItemUpdate)直接調(diào)用 OnSearch 方法,觸發(fā)查詢。此處不用像上面處理 OnKeyDown 那樣等待156毫秒,因?yàn)?OnSelectedItemUpdate 是在 warningSigns 更新后觸發(fā)的。
點(diǎn)擊清空?qǐng)D標(biāo)觸發(fā)查詢
很簡(jiǎn)單,只要給 MTextField 和 MSelect 組件添加以下屬性:
Clearable OnClearClick="OnSearch"

加點(diǎn)Loading動(dòng)畫可好?
好!
<MButton Color="primary"
Loading="searching"
OnClick="HandleOnSearch">
搜索
</MButton>
...
<MDataTable Headers="_headers" Items="forecasts"
Loading="loading"
ItemsPerPage="5" Class="elevation-1">
@code {
private bool loading;
private bool searching;
private async Task HandleOnSearch()
{
searching = true;
await OnSearch();
searching = false;
}
private async Task OnSearch()
loading = true;
await Task.Delay(1000);
forecasts = await ForecastService.GetForecastAsync(summary, warningSigns);
loading = false;
}Line 2-3,15,17-24
新增 searching 變量用于控制搜索按鈕的 Loading 狀態(tài),同時(shí)新增了 HandleOnSearch 代替原來的 OnSearch 是為了單獨(dú)控制點(diǎn)擊搜索按鈕的動(dòng)畫。
Line 9,14,28,33
新增 loading 變量用于控制 MDataTable 的 Loading 狀態(tài)。OnSearch 方法塊中在接口請(qǐng)求前后設(shè)置 loading 的值。

表的行操作和自定義列樣式
因?yàn)槠拗疲揖筒灰灰话汛a貼出來了,具體代碼請(qǐng)查閱 源碼 接下來我將針對(duì)Table寫一些常見的代碼,如行操作和自定義列樣式。

封裝組件和技巧
我本應(yīng)該用這節(jié)分享的內(nèi)容將上面的例子重構(gòu)的過程寫出來,但感覺會(huì)使得本文太冗長(zhǎng)。重構(gòu)后的代碼我也會(huì)上傳到 Github 上。
封裝組件
試想一下,當(dāng)你被分配到好幾個(gè)模塊,每個(gè)模塊都有至少一個(gè)查詢表格頁,你會(huì)如何開發(fā)?你大概會(huì)說復(fù)制最合適的代碼文件,然后重命名文件名,重命名相應(yīng)的變量,修修改改就完行了。當(dāng)然這是一個(gè)方法,但不優(yōu)雅。那優(yōu)雅的方式是什么,是封裝。我有段時(shí)間在全職開發(fā) MASA.Blazor 組件庫(kù),后面因?yàn)闃I(yè)務(wù)需求分配到了IoT項(xiàng)目幫助Blazor后臺(tái)系統(tǒng)的研發(fā)和 MASA.Blazor 的實(shí)踐。在開發(fā)IoT項(xiàng)目時(shí),經(jīng)常會(huì)看見相同的代碼分布在相同的類中,我試著優(yōu)化重構(gòu)這些代碼,并從查詢表格頁中抽離封裝了以下幾個(gè)組件:
- Filters:接收
OnSearch參數(shù)代理查詢,通過context提供onEnter和onSearch方法供單個(gè)查詢組件使用。 - PageHeader:一個(gè)標(biāo)準(zhǔn)的頁頭,包括了標(biāo)題、副標(biāo)題、搜索按鈕,并提供
Filters組件的能力。 - Actions:提供一組操作按鈕,默認(rèn)展示前兩個(gè),后面的按鈕會(huì)移動(dòng)到
MMenu中顯示。 - BlockText:將相同類型的兩個(gè)數(shù)據(jù)并列顯示。ColorChip:提供有限的顏色列表生成帶淺色字體的
MChip。 - CopyableText:在文本后提供可以復(fù)制內(nèi)容的圖標(biāo)按鈕。
- DateTimePicker:提高帶時(shí)分秒選擇器的彈出層時(shí)間選擇器。
- EllipsisText:根據(jù)父級(jí)盒子的寬度自動(dòng)截?cái)辔谋?。GenericColumnRender:渲染DateTime、枚舉、bool和其他類型值??梢杂糜?code>MDataTable的
ItemColContent和Definitions的DetailContent。
PageHeader組件作為 MASA.Blazor 預(yù)置組件的一部分已經(jīng)發(fā)布,其他提及的組件還沒有并入 MASA.Blazor 主庫(kù)。如果你想要使用或參考,可以訪問 MASA.Blazor.Experimental.Components。關(guān)于預(yù)置組件和實(shí)驗(yàn)性組件的詳細(xì)介紹和使用的文章,后面會(huì)由其他同事編寫和發(fā)布,請(qǐng)大家?guī)Ф喽嚓P(guān)注!
MASA.Blazor.Experimental.Components 是一個(gè)實(shí)驗(yàn)性組件庫(kù),這意味著該庫(kù)的API和功能可能會(huì)被重新設(shè)計(jì)。不過隨著實(shí)驗(yàn)性組件的功能不斷完善和穩(wěn)定,會(huì)隨著 MASA.Blazor 版本的更新而并入主庫(kù)。
技巧
善用基類
Blazor的組件其實(shí)也是一個(gè)類,它默認(rèn)繼承自 ComponentBase 并提供了許多虛擬方法,我們可以重寫它們來影響應(yīng)用程序的行為。而這些方法通過繼承機(jī)制給所有Blazor組件使用。
在實(shí)際開發(fā)中,我會(huì)發(fā)現(xiàn)幾乎每個(gè)頁面都會(huì)注入 NavigationManager、IJsRunTime 和其他可能存在的業(yè)務(wù)服務(wù),或者會(huì)使用某些共同使用的組件,那我們可以在繼承 ComponentBase 的基礎(chǔ)上再寫一個(gè)已經(jīng)使用了這些服務(wù)和組件的基類。
按架構(gòu)可以創(chuàng)建專門給 @page 組件用的 PageComponentBase 和單純封裝功能的 PureComponentBase。
按業(yè)務(wù)分類就得看情況了,因?yàn)闃I(yè)務(wù)更加具體,基類里通常會(huì)有注入 HttpClient 或者同類型業(yè)務(wù)服務(wù),以及任何共同使用的代碼。
SetParametersAsync
SetParametersAsync sets parameters supplied by the component's parent in the render tree or from route parameters.
只需知道每當(dāng)父級(jí)呈現(xiàn)時(shí),都會(huì)執(zhí)行此方法。這意味著它是指定默認(rèn)參數(shù)值的正確位置。
拿前面的例子來說,在使用 MTextField 和 MSelect 時(shí)都會(huì)設(shè)置以下代碼來維持相同的外觀和行為:
Clearable
Dense
HideDetails="@("auto")"
Outlined那么與其每次都要寫一遍,不如利用 SetParametersAsync 的特性把這些默認(rèn)參數(shù)提前設(shè)置:
<DefaultTextField @bind-Value="@summary"
OnKeyDown="@context.onEnter"
OnClearClick="@context.onSearch"
Label="Summary">
</DefaultTextField>
<DefaultSelect @bind-Value="warningSigns"
Items="@(Enum<WarningSigns>.GetEnumObjectList<WarningSigns>())"
ItemText="item => item.Name"
ItemValue="item => item.Value"
TValue="WarningSigns?"
TItem="EnumObject<WarningSigns>"
TItemValue="WarningSigns"
Label="高溫警告"
OnSelectedItemUpdate="@context.onSearch"
OnClearClick="@context.onSearch">
</DefaultSelect>
<DefaultTextField @bind-Value="@summary"
OnKeyDown="@context.onEnter"
OnClearClick="@context.onSearch"
Label="Summary">
</DefaultTextField>
<DefaultSelect @bind-Value="warningSigns"
Items="@(Enum<WarningSigns>.GetEnumObjectList<WarningSigns>())"
ItemText="item => item.Name"
ItemValue="item => item.Value"
TValue="WarningSigns?"
TItem="EnumObject<WarningSigns>"
TItemValue="WarningSigns"
Label="高溫警告"
OnSelectedItemUpdate="@context.onSearch"
OnClearClick="@context.onSearch">
</DefaultSelect>
未來的計(jì)劃
未來我們團(tuán)隊(duì)將繼續(xù)優(yōu)化各個(gè)組件的性能,完成缺失的組件,解決BUG問題,完善文檔等。另外,我們也計(jì)劃出Blazor相關(guān)的教程和分享文章,敬請(qǐng)期待。
感謝閱讀!
資源源碼?
https://github.com/capdiem/MasaBlazorStandardTablePage
參考
https://github.com/BlazorComponent/Masa.Blazor
https://github.com/capdiem/MASA.Blazor.Experimental.Components
開源地址
MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks
MASA.Contrib:https://github.com/masastack/MASA.Contrib
MASA.Utils:https://github.com/masastack/MASA.Utils
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
到此這篇關(guān)于使用MASA Blazor開發(fā)一個(gè)標(biāo)準(zhǔn)的查詢表格頁的文章就介紹到這了,更多相關(guān)MASA Blazor查詢表格頁內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用Meta標(biāo)簽控制360瀏覽器默認(rèn)極速模式打開自己的網(wǎng)站
最近用360瀏覽器訪問自己的網(wǎng)站,發(fā)現(xiàn)都是被優(yōu)先選用兼容模式打開,這使得網(wǎng)站很難看。為了讓360瀏覽器打開網(wǎng)站的時(shí)候優(yōu)先使用極速模式,而非兼容模式,找了一下官方論壇,發(fā)現(xiàn)了解決方案。2016-07-07
win11?C盤出現(xiàn)鎖和黃色感嘆號(hào)的解決方法
這篇文章主要介紹了win11?C盤出現(xiàn)鎖和黃色感嘆號(hào)的解決方法,文中有詳細(xì)的解決方案,對(duì)大家的解決問題有一定的幫助,需要的朋友可以參考下2007-02-02
IntelliJ IDEA 2020如何設(shè)置背景圖片的方法步驟
這篇文章主要介紹了IntelliJ IDEA 2020如何設(shè)置背景圖片的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
git流水線(Pipeline)導(dǎo)致分支(Branch)無法合并問題及解決
這篇文章主要介紹了git流水線(Pipeline)導(dǎo)致分支(Branch)無法合并問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11

