返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >使用MASA Blazor开发查询表格页
  • 351
分享到

使用MASA Blazor开发查询表格页

2024-04-02 19:04:59 351人浏览 独家记忆
摘要

目录前言手撸查询表格页创建应用程序支持单个查询条件和搜索将随机数据替换成模拟数据添加查询输入框和搜索按钮支持多个查询条件和重置更新 WeatherForecastService 以支

前言

大家好,我是开源项目 MASA blazor 主要开发者之一,如果你还不了解MASA Blazor,可以访问我们的 官网 和博客 《初识MASA Blazor》 一探究竟。简单来说,MASA Blazor 是一个基于 Material Design 设计语言的 Blazor 组件库,dotnet开发者只需或者甚至不需要懂得 javascript 就能开发一个企业级中后台系统。

我这次分享的主题是《使用MASA Blazor开发一个标准的查询表格页》,我会先从创建项目开始手撸一个没有任何技巧的查询表格页,然后我会分享一些技巧和封装的组件,实现快速开发。

手撸查询表格页

创建应用程序

关于如何安装MASA Blazor模板,请移步 MASA.Blazor快速入门

首先通过MASA Blazor模板默认的Server项目,项目命名为 MasaBlazorStandardTablePage。

dotnet new --install MASA.Template
dotnet new masab -o MasaBlazorStandardTablePage

通过CLI运行应用程序,或直接通过vs启动项目。

cd MasaBlazorStandardTablePage
dotnet run

启动成功后切换到 Fetch data 页面,此页面展示了一个简单的使用了 MDataTable 的表格。

支持单个查询条件和搜索

让我们从最简单的单个条件查询开始。

将随机数据替换成模拟数据

修改 WeatherForecastService,将随机数据替换成死数据以便支持查询功能。下面的代码更新了数据来源和 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());
        }
    }

同时修改 FetchData.razor,因为 WeatherForecastService.GetForecastAsync() 删除了 startDate 入参。

protected override async Task OnInitializedAsync()
{
    await Task.Delay(1000); // 模拟真实环境,触发Loading效果
    forecasts = await ForecastService.GetForecastAsync(); // here
}

添加查询输入框和搜索按钮

在 FetchData.razor 页面中的 <p> 标签下添加以下代码

<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

定义了一个 string 类型的名为 summary 的变量,双向绑定给了 MTextField 组件。MTextFiled 除了 @bind-Value 属性用于设置双向绑定,其他属性的含义请阅读 文档。

Line 12

定义了一个搜索按钮,用于触发查询。

修改 WeatherForecastService.GetForecastAsync 方法,增加 summary 入参,并支持查询。

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());
}

支持多个查询条件和重置

现在让我们再添加一个高温预警的选择框来查询不同高温预警状态的数据。

更新 WeatherForecastService 以支持根据高温预警筛选数据

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());
}

增加高温预警选择框

在 Data 目录下添加名为 WarningSigns 的枚举。

public enum WarningSigns
{
    [Description("高温黄色预警 35℃")]
    Yellow = 1,
    [Description("高温橙色预警 37℃")]
    Orange,
    [Description("高温红色预警 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

通过设置 Sm="6" 可以让屏幕尺寸大于768px时一行占两个 MCol ,实现 MTextFieldMSelect 并排显示。

Line 11-23,33,44

第33行定义 warningSigns 变量用于接收 MSelect 选中的值,当然也可以通过设置值更新 MSelect 选中的值,只要设置了 @bind-Value 双向绑定就行,就像第11行那样。第12行使用了 Masa.Utils.Enums 提供的方法,返回了一个包含Name(Description)和Value(枚举值)的列表,赋值给了 MSelect.Items 。第44行将 warningSigns 的传给查询接口。

Line 27,35-40

此处定义了一个重置按钮,用于清空所有查询输入框的内容并刷新表格。

支持键入回车或选择后触发查询

后来测试小姐姐说你这太难用了,回车不能触发搜索,选择完也不能触发搜索。好吧好吧,我们现在加上。

键入回车后触发

原理即捕捉 OnKeyDown 事件是否点击了 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毫秒,预防输入的值在更新到变量之前按下Enter键
            await Task.Delay(156);

            await OnSearch();
        }
    }
}

Line 2

HandleOnKeyDown 绑定到 MTextFieldOnKeyDown 事件。

Line 10-17

通过判断 KeyboardEventArgsCode 值是否为 Enter 来触发搜索。第14行等待156毫秒是为了等待 summary 的值已经是输入过后的值。

选择后触发查询

<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

当选择项更新时(OnSelectedItemUpdate)直接调用 OnSearch 方法,触发查询。此处不用像上面处理 OnKeyDown 那样等待156毫秒,因为 OnSelectedItemUpdate 是在 warningSigns 更新后触发的。

点击清空图标触发查询

很简单,只要给 MTextFieldMSelect 组件添加以下属性:

Clearable
OnClearClick="OnSearch"

加点Loading动画可好?

好!

<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 状态,同时新增了 HandleOnSearch 代替原来的 OnSearch 是为了单独控制点击搜索按钮的动画。

Line 9,14,28,33

新增 loading 变量用于控制 MDataTableLoading 状态。OnSearch 方法块中在接口请求前后设置 loading 的值。

表的行操作和自定义列样式

因为篇幅限制,我就不一一把代码贴出来了,具体代码请查阅 源码 接下来我将针对Table写一些常见的代码,如行操作和自定义列样式。

封装组件和技巧

我本应该用这节分享的内容将上面的例子重构的过程写出来,但感觉会使得本文太冗长。重构后的代码我也会上传到 GitHub 上。

封装组件

试想一下,当你被分配到好几个模块,每个模块都有至少一个查询表格页,你会如何开发?你大概会说复制最合适的代码文件,然后重命名文件名,重命名相应的变量,修修改改就完行了。当然这是一个方法,但不优雅。那优雅的方式是什么,是封装。我有段时间在全职开发 MASA.Blazor 组件库,后面因为业务需求分配到了IoT项目帮助Blazor后台系统的研发和 MASA.Blazor 的实践。在开发IoT项目时,经常会看见相同的代码分布在相同的类中,我试着优化重构这些代码,并从查询表格页中抽离封装了以下几个组件:

  • Filters:接收OnSearch参数代理查询,通过context提供onEnteronSearch方法供单个查询组件使用。
  • PageHeader:一个标准的页头,包括了标题、副标题、搜索按钮,并提供Filters组件的能力。
  • Actions:提供一组操作按钮,默认展示前两个,后面的按钮会移动到MMenu中显示。
  • BlockText:将相同类型的两个数据并列显示。ColorChip:提供有限的颜色列表生成带浅色字体的MChip
  • CopyableText:在文本后提供可以复制内容的图标按钮。
  • DateTimePicker:提高带时分秒选择器的弹出层时间选择器。
  • EllipsisText:根据父级盒子的宽度自动截断文本。GenericColumnRender:渲染DateTime、枚举、bool和其他类型值。可以用于MDataTableItemColContentDefinitionsDetailContent

PageHeader组件作为 MASA.Blazor 预置组件的一部分已经发布,其他提及的组件还没有并入 MASA.Blazor 主库。如果你想要使用或参考,可以访问 MASA.Blazor.Experimental.Components。关于预置组件和实验性组件的详细介绍和使用的文章,后面会由其他同事编写和发布,请大家带多多关注!

MASA.Blazor.Experimental.Components 是一个实验性组件库,这意味着该库的api和功能可能会被重新设计。不过随着实验性组件的功能不断完善和稳定,会随着 MASA.Blazor 版本的更新而并入主库。

 

技巧

善用基类

Blazor的组件其实也是一个类,它默认继承自 ComponentBase 并提供了许多虚拟方法,我们可以重写它们来影响应用程序的行为。而这些方法通过继承机制给所有Blazor组件使用。

在实际开发中,我会发现几乎每个页面都会注入 NavigationManagerIjsRunTime 和其他可能存在的业务服务,或者会使用某些共同使用的组件,那我们可以在继承 ComponentBase 的基础上再写一个已经使用了这些服务和组件的基类。

架构可以创建专门给 @page 组件用的 PageComponentBase 和单纯封装功能的 PureComponentBase
按业务分类就得看情况了,因为业务更加具体,基类里通常会有注入 HttpClient 或者同类型业务服务,以及任何共同使用的代码。

SetParametersAsync

SetParametersAsync sets parameters supplied by the component's parent in the render tree or from route parameters.

只需知道每当父级呈现时,都会执行此方法。这意味着它是指定默认参数值的正确位置。
拿前面的例子来说,在使用 MTextFieldMSelect 时都会设置以下代码来维持相同的外观和行为:

Clearable
Dense
HideDetails="@("auto")"
Outlined

那么与其每次都要写一遍,不如利用 SetParametersAsync 的特性把这些默认参数提前设置:

<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>

未来的计划

未来我们团队将继续优化各个组件的性能,完成缺失的组件,解决BUG问题,完善文档等。另外,我们也计划出Blazor相关的教程和分享文章,敬请期待。

感谢阅读!

资源源码​

https://github.com/capdiem/MasaBlazorStandardTablePage

参考

https://blazor.masastack.com/

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

到此这篇关于使用MASA Blazor开发一个标准的查询表格页的文章就介绍到这了,更多相关MASA Blazor查询表格页内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 使用MASA Blazor开发查询表格页

本文链接: https://www.lsjlt.com/news/147448.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 使用MASA Blazor开发查询表格页
    目录前言手撸查询表格页创建应用程序支持单个查询条件和搜索将随机数据替换成模拟数据添加查询输入框和搜索按钮支持多个查询条件和重置更新 WeatherForecastService 以支...
    99+
    2024-04-02
  • .NET6开发TodoList应用之实现查询分页
    目录需求目标原理与思路实现定义分页结果数据结构添加对于分页结果的Mapping Profile创建分页查询请求创建查询Controller验证总结需求 查询中有个非常常见的需求就是后...
    99+
    2024-04-02
  • MyBatis多表查询和注解开发
    文章目录 Mybatis多表查询一对一查询一对一查询的模型一对一查询的语句创建Order和User实体创建OrderMapper接口配置OrderMapper.xml测试结果 一对多查询一对多查询的模型一对多查询的语句修改Us...
    99+
    2023-08-19
    mybatis java mysql 原力计划
  • mysql回表查询是什么,回表查询的使用
    目录聚集索引和非聚集索引聚集索引和非聚集索引的区别那回表是什么验证在说到什么是回表查询的时候,有两个概念需要先解释清楚:分别是聚集索引(聚簇索引)和非聚集索引(非聚簇索引) 聚集索引和非聚集索引 mysql规定,在使用I...
    99+
    2022-11-21
    mysql查询 mysql回表查询 回表查询
  • web开发如何设置网页表格边框
    小编给大家分享一下web开发如何设置网页表格边框,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!前面学了网页表格中的单元格线条的设置方法,今天学习网页表格的边框线的...
    99+
    2023-06-08
  • SpringDataJpa如何使用union多表分页条件查询
    目录如何使用union多表分页条件查询条件分页踩过的坑分享几个用到的mysql语法jpa执行原生sql union bug解决如何使用union多表分页...
    99+
    2024-04-02
  • SpringDataJpa怎么使用union多表分页条件查询
    本篇内容介绍了“SpringDataJpa怎么使用union多表分页条件查询”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!如何使用...
    99+
    2023-06-29
  • 使用多个单表查询,还是使用一个多表联合查询?
    1. 从逻辑架构分层原则来看  关联关系代表了业务规则/逻辑,毫无约束大量使用关联查询,就是把大量的业务规则和逻辑放在数据库来执行了,数据库消耗cpu、内存、io等资源进行关联操作,实际上是在做应...
    99+
    2024-04-02
  • TK-MyBatis分页查询怎么使用
    本篇内容介绍了“TK-MyBatis分页查询怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!记 tkMybatis 查询出一个 &nb...
    99+
    2023-06-21
  • 使用MySQL如何实现分页查询
    目录一、分页1. 什么是分页2. 真分页3. 假分页4. 缓存层二、MySQL实现分页1. LIMIT用法2. 分页公式8种MySQL分页方法总结方法1: 直接使用数据库提供的SQL...
    99+
    2024-04-02
  • 使用jquery实现分页查询数据
    随着 Web 技术的不断发展,越来越多的网站需要支持分页查询数据功能。而 jQuery 是一种非常流行的 JavaScript 库,能够帮助开发人员更加方便地操作 DOM、事件、动画等方面,因此使用 jQuery 实现分页查询数据是一个不错...
    99+
    2023-05-14
  • TK-MyBatis分页查询的具体使用
    记 tkMybatis 查询出一个  List集合 该集合已经做好了一层分页Page封装 即查询出的list 使用类型判断 instanceof Page 为true 但是,中途不明...
    99+
    2024-04-02
  • jQuery中EasyUI开发如何实现查询提交表单
    这篇文章主要介绍jQuery中EasyUI开发如何实现查询提交表单,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!查询提交表单:function serarchFun(){/...
    99+
    2024-04-02
  • oracle查询表空间使用情况
    ...
    99+
    2014-07-28
    oracle查询表空间使用情况
  • 使用T-SQL实现多表查询
    表连接的类型:1.内连接(inner join):是最常用的一种连接方式,只返回两个数据集合之间匹配关系的行,将位于两个互相交叉的数据集合中重叠部分以内的数据行连接起来。 例子:在表A和表B中使用...
    99+
    2024-04-02
  • oracle数据库怎么用网页发布表格
    使用 html 和 oracle 数据库发布表格需要以下步骤:1. 创建 html 页面;2. 使用 php 连接到 oracle;3. 查询数据;4. 填充 html 表格;5. 关闭...
    99+
    2024-05-13
    oracle
  • 使用mybatis格式化查询出的日期
    mybatis格式化查询出的日期 1、格式符说明 %Y:年 示例:2019 %m:月 示例:08 %d:日 示例:05 %H:时 示例:15 %I:分 示例:47 %S:秒 示例:5...
    99+
    2024-04-02
  • 页面查询案例(使用redis数据库)
    需求: 提供一个index.html页面,页面中有个省份,下拉列表2.当页面加载完成时,发送ajax请求。加载所有省份   前期项目初步搭建: index.html $(function(){ $.get("url",{},f...
    99+
    2015-11-16
    页面查询案例(使用redis数据库)
  • 如何使用Bootstrap4 + Vue2实现分页查询
    小编给大家分享一下如何使用Bootstrap4 + Vue2实现分页查询,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!写在前面工...
    99+
    2024-04-02
  • MyBatis如何使用PageHelper实现分页查询
    目录使用PageHelper实现分页查询1、创建数据表2、创建项目2.1 创建实体类(Entity层)2.2 数据库映射层(Mapper层)3、运行测试MyBatis PageHel...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作