我目前正在使用MudBlazor,十分喜欢它。
但有些东西我发现自己不断地向组件中添加,如CancellationTokens,还有自定义模板。
有没有一种方法可以完全继承/扩展现有的组件?
一种选择是创建一个新的组件,该组件具有我想要修改的组件的实例,并将所有参数添加到我的组件中,然后将它们映射回原始组件,但我认为肯定有更好的方法。
我目前正在使用MudBlazor,十分喜欢它。
但有些东西我发现自己不断地向组件中添加,如CancellationTokens,还有自定义模板。
有没有一种方法可以完全继承/扩展现有的组件?
一种选择是创建一个新的组件,该组件具有我想要修改的组件的实例,并将所有参数添加到我的组件中,然后将它们映射回原始组件,但我认为肯定有更好的方法。
属性扩展在创建其他组件的包装器或更高级抽象时非常方便:
<MudTextField Variant="@Variant" @attributes="@OtherAttributes"></MudTextField>
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object> OtherAttributes { get; set; }
[Parameter]
// can even set your own defaults
public Variant Variant { get; set; } = "Variant.Filled"
}
您还可以创建自己的基础组件,并使用@inherits
来共享逻辑和参数。
您可以像任何其他非密封类一样继承 Blazor 组件
using Microsoft.AspNetCore.Components;
using MudBlazor;
namespace MyMudBlazor;
public partial class MyMudButton : MudButton
{
[Parameter] public bool IsEnabled
{
get { return !base.Disabled; }
set { base.Disabled = !value; }
}
}
听起来你很可能想要在自己的新组件中@inherit MudBlazor 组件。这实际上允许你将 MudBlazor 组件用作你的新类/组件的基类,避免重新定义 MudBlazor 组件已经定义的所有参数。
这可以在 C# 或者 razor 中完成。下面是一个 razor 示例,OutlinedMudButton.razor
,它允许用户仍然设置所有常规的 MudButton 参数,除了 Variant
参数:
@inhertis MudButton
@code {
// Hide the MudButton's Variant parameter so it can not be changed by users.
protected new Variant Variant { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
base.Variant = Variant.Outlined;
}
}
@{
// Display the base component that we are inheriting from.
base.BuildRenderTree(__builder);
}
根据您的使用情况,您可能希望使用组合而不是继承,通过创建一个新的组件,其中仅包含您想要装饰的 MudBlazor 组件的实例。这可能更容易或更合适,特别是如果您想隐藏许多 MudBlazor 组件的参数,以防止用户更改它们。请注意,如果您像其他答案/评论中建议的那样使用 属性扩展,缺点是您的组件将无法为所有 MudBlazor 组件的参数提供编辑器智能感知。
这里是另一个 Razor 示例,OutlinedMudButton.razor
,它创建了一个带有 Outlined MudButton 的组件,用户只能设置按钮的 Text
属性:
<MudButton Variant="Variant.Outlined">@Text</MudButton>
@code {
[Parameter]
public string Text { get; set;}
}
base.BuildRenderTree(__builder)
的重要说明,您不能在RenderFragment中执行此操作(即包装在另一个组件中)。有关解决方案,请参阅此答案。 - Conman_123.razor
组件。它可以消耗我想要的任何服务,添加事件处理程序等等。所以,与其使用继承,我更喜欢拖入一个处理业务逻辑的子组件。如果它还有方法,那么我会在组件的标记中添加一个@ref。我的许多页面都是这样的。<FontSizeUtility UserId = @UserId />
<TimerUtility @ref=MyTimer TimerTicker = HandleTimerTick />
@code{
TimerUtility MyTimer = new();
. . .
async Task HandleTimerTick(){
}
}
MudNumericField
组件,以便用户可以输入百分比值,但底层值将是小数值。例如,用户输入98,但.98绑定到变量。最后,我采用了@deadlydog建议的组合方式。
https://try.mudblazor.com/snippet/cEmnbPnOhAGpDEzB
<MudNumericField
@bind-Value="DisplayValue"
Label="@Label"
Variant="@Variant"
Margin="@Margin"
Adornment="@Adornment"
AdornmentIcon="@AdornmentIcon"
Clearable="@Clearable"
HideSpinButtons="@HideSpinButtons"
Format="@Format"
/>
@code {
private decimal? _value;
private decimal? _displayValue;
[Parameter] public string Label { get; set; }
[Parameter] public Variant Variant { get; set; }
[Parameter] public Margin Margin { get; set; }
[Parameter] public Adornment Adornment { get; set; } = Adornment.End;
[Parameter] public string AdornmentIcon { get; set; } = @Icons.Material.Filled.Percent;
[Parameter] public bool HideSpinButtons { get; set; } = true;
[Parameter] public bool Clearable { get; set; }
[Parameter] public string Format { get; set; } = "#.#";
[Parameter] public EventCallback<decimal?> ValueChanged { get; set; }
[Parameter] public decimal? Value
{
get => _value;
set
{
_value = value;
}
}
private decimal? DisplayValue
{
get => _displayValue;
set
{
_displayValue = value;
_value = value / 100;
ValueChanged.InvokeAsync(_value);
}
}
protected override void OnParametersSet()
{
var convertedInput = Value * 100;
if(convertedInput != DisplayValue) {
DisplayValue = convertedInput;
}
}
}