You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写Blazor自定义组件实现按键过滤?解决InputNumber Firefox兼容问题

自定义Blazor输入组件实现通用字符过滤(解决Firefox下InputNumber失效问题)

问题背景

Blazor自带的InputNumber组件会渲染<input type="number">,但这个原生输入框在Firefox里不会限制非数字输入。我尝试写了一个自定义过滤组件,虽然<p>标签能正确显示过滤后的数值,但输入框本身还是会显示所有按下的字符,怎么解决这个问题?要求方法支持任意字符过滤,不只是数字。

我的尝试代码:

@inherits InputNumber<int?>

<input type="number" @bind=_value @onkeypress=OnKeypress />
<p>@_value</p>

@code {
  private string _value;

  private void OnKeypress(KeyboardEventArgs e) {
    if (Regex.IsMatch(e.Key, "[0-9]"))
      _value += e.Key;
  }
}

解决方案

你之前的问题出在@bind和手动按键处理的冲突:@bind会自动同步输入框的原生值和你的_value变量,导致你过滤后的_value和输入框实际显示的值不一致。要解决这个问题,需要阻止不符合规则的按键默认行为,同时自己控制输入框的显示值,还要和InputNumber的Value保持同步。

1. 通用过滤组件实现

下面是一个支持自定义过滤规则的组件,不仅能处理数字,还能适配任意字符过滤需求:

@inherits InputNumber<TValue>
@using System.Globalization

<input 
    type="text" 
    value="@_displayValue" 
    @oninput="OnInput"
    @onkeydown="OnKeyDown"
    />

@code {
    private string _displayValue;

    // 自定义过滤规则参数,外部传入判断逻辑
    [Parameter] public Func<string, bool> CharacterFilter { get; set; } = _ => true;

    protected override void OnInitialized()
    {
        // 初始化时同步Value到显示值
        _displayValue = CurrentValueAsString;
        base.OnInitialized();
    }

    protected override void OnParametersSet()
    {
        // 当外部Value变化时更新显示值
        if (!EqualityComparer<TValue>.Default.Equals(CurrentValue, ParseValueFromString(_displayValue)))
        {
            _displayValue = CurrentValueAsString;
        }
        base.OnParametersSet();
    }

    private void OnInput(ChangeEventArgs e)
    {
        var inputValue = e.Value?.ToString() ?? string.Empty;
        // 应用过滤规则,保留符合要求的字符
        var filteredValue = new string(inputValue.Where(c => CharacterFilter(c.ToString())).ToArray());
        
        // 同步到组件的Value
        if (TryParseValueFromString(filteredValue, out var parsedValue, out var validationErrorMessage))
        {
            CurrentValue = parsedValue;
            _displayValue = filteredValue;
        }
        else
        {
            // 解析失败时回显过滤后的值,同时保留验证逻辑
            _displayValue = filteredValue;
        }
    }

    private void OnKeyDown(KeyboardEventArgs e)
    {
        // 允许控制键(比如退格、删除、方向键)
        var isControlKey = e.Key is "Backspace" or "Delete" or "ArrowLeft" or "ArrowRight" or "Tab";
        if (isControlKey) return;

        // 如果输入的字符不符合过滤规则,阻止默认行为
        if (!CharacterFilter(e.Key))
        {
            e.PreventDefault();
        }
    }
}

2. 使用示例(数字过滤)

在页面中引用这个组件,传入数字过滤规则:

<CustomFilterInputNumber TValue="int?" 
    @bind-Value="@MyNumber"
    CharacterFilter="@(c => Regex.IsMatch(c, "[0-9]"))" />

@code {
    private int? MyNumber;
}

关键要点说明

  • 改用type="text"替代type="number":原生number输入框在不同浏览器行为不一致,用文本输入框能完全控制输入内容
  • 双层面过滤:OnKeyDown阻止不符合规则的按键输入,OnInput处理粘贴等非按键输入场景(比如右键粘贴),确保所有输入都被过滤
  • 可自定义过滤规则:通过CharacterFilter参数传入任意判断逻辑,比如只允许字母、特定符号等
  • 保留InputNumber的原有功能:继承自InputNumber,所以自带验证、双向绑定等特性,不需要重新实现

内容的提问来源于stack exchange,提问作者lonix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 10:10:40