如何继承MudButton并扩展点击加载状态?求优化方案
我已经实现了为MudButton添加点击加载状态的扩展逻辑,但不确定是否为最佳实践,希望得到优化建议。以下是我的实现代码:
实现代码
MudButtonLoading.razor
@inherits MudButton <MudElement @bind-Ref="@_elementReference" HtmlTag="@HtmlTag" Class="@Classname" Style="@Style" @attributes="UserAttributes" @onclick="OnClickHandler" type="@ButtonType.ToDescriptionString()" href="@Href" target="@Target" rel="@GetRel()" disabled="@disabledState" ClickPropagation="@ClickPropagation"> <span class="mud-button-label"> @if (!string.IsNullOrWhiteSpace(StartIcon)) { <span class="@StartIconClass"> @if (!isProcessing) { <MudIcon Icon="@StartIcon" Size="@(IconSize ?? Size)" Color="@IconColor" /> } else { <MudProgressCircular Class="ms-n1" Size="LoadingSize" Indeterminate="true" /> } </span> } @if (isProcessing) { @if (string.IsNullOrWhiteSpace(StartIcon) && string.IsNullOrWhiteSpace(EndIcon)) { <MudProgressCircular Class="ms-n1" Size="LoadingSize" Indeterminate="true" /> } } @ChildContent @if (!string.IsNullOrWhiteSpace(EndIcon)) { <span class="@EndIconClass"> @if (!isProcessing) { <MudIcon Icon="@EndIcon" Size="@(IconSize ?? Size)" Color="@IconColor" /> } else { <MudProgressCircular Class="ms-n1" Size="LoadingSize" Indeterminate="true" /> } </span> } </span> </MudElement>
MudButtonLoading.razor.cs
using Microsoft.AspNetCore.Components.Web; using MudBlazor; namespace Sample.Client.Components.Buttons { public partial class MudButtonLoading { protected bool isProcessing; protected bool disabledState => base.GetDisabledState() || isProcessing; protected override async Task OnClickHandler(MouseEventArgs ev) { try { isProcessing = true; //StateHasChanged(); //await Task.Delay(1); await base.OnClickHandler(ev); } finally { isProcessing = false; } } protected Size LoadingSize => IconSize ?? Size switch { Size.Small => Size.Small, var other => other - 1 }; } }
优化建议
1. 支持外部双向控制加载状态
目前加载状态仅由按钮内部点击触发,实际场景中可能需要外部逻辑手动控制(比如表单校验后触发加载)。可以新增参数实现双向绑定:
[Parameter] public bool IsProcessing { get; set; } [Parameter] public EventCallback<bool> IsProcessingChanged { get; set; } // 替换原有的isProcessing字段,改为使用绑定参数 protected bool disabledState => base.GetDisabledState() || IsProcessing; protected override async Task OnClickHandler(MouseEventArgs ev) { try { if (!IsProcessing) { await IsProcessingChanged.InvokeAsync(true); } await base.OnClickHandler(ev); } finally { if (IsProcessing) { await IsProcessingChanged.InvokeAsync(false); } } }
2. 提取重复渲染逻辑,减少代码冗余
StartIcon和EndIcon的加载状态渲染逻辑完全重复,可以提取为复用的RenderFragment:
@code { private RenderFragment RenderIconOrLoader(string icon, string iconClass) => __builder => { if (!IsProcessing) { <span class="@iconClass"> <MudIcon Icon="@icon" Size="@(IconSize ?? Size)" Color="@IconColor" /> </span> } else { <span class="@iconClass"> <MudProgressCircular Class="mud-margin-left-n1" Size="LoadingSize" Indeterminate="true" /> </span> } }; } // 在Razor模板中替换原有代码: @if (!string.IsNullOrWhiteSpace(StartIcon)) { @RenderIconOrLoader(StartIcon, StartIconClass) } // 同理替换EndIcon部分
3. 确保加载状态UI及时更新
在设置IsProcessing=true后,若base.OnClickHandler执行过快,Blazor可能来不及更新UI。可以通过await Task.Yield()让UI线程优先渲染加载状态:
protected override async Task OnClickHandler(MouseEventArgs ev) { try { await IsProcessingChanged.InvokeAsync(true); await Task.Yield(); // 让出UI线程,确保加载状态渲染完成 await base.OnClickHandler(ev); } finally { await IsProcessingChanged.InvokeAsync(false); } }
4. 增强可配置性,支持自定义加载内容
默认的进度环不一定满足所有场景,允许用户传入自定义加载内容会提升组件灵活性:
[Parameter] public RenderFragment LoadingContent { get; set; } // 在Razor模板中替换默认进度环: @if (IsProcessing) { @if (string.IsNullOrWhiteSpace(StartIcon) && string.IsNullOrWhiteSpace(EndIcon)) { @(LoadingContent ?? (RenderFragment)(__builder => { <MudProgressCircular Class="mud-margin-left-n1" Size="LoadingSize" Indeterminate="true" /> })) } }
5. 优化尺寸计算与样式一致性
LoadingSize的计算可以更贴合MudBlazor的尺寸规范,同时使用官方推荐的样式类名:
protected Size LoadingSize => IconSize ?? Size switch { Size.Small => Size.Small, Size.Medium => Size.Small, Size.Large => Size.Medium, _ => Size.Small }; // 将原有的ms-n1替换为官方类名mud-margin-left-n1,保持样式体系一致性
内容的提问来源于stack exchange,提问作者Bi Nguyễn
相关产品推荐
相关产品推荐

