如何为Blazor文本框的onChange事件添加节流处理
Blazor文本框输入节流实现方案
核心问题解答
完全可以用JavaScript(比如setTimeout)实现节流,同时Blazor也支持纯C#的节流实现,两种方案都能满足输入停止后延迟触发事件的需求,可根据开发习惯选择。
先解决你遇到的<InputText>不识别问题
<InputText>是Blazor官方表单组件,需要在组件顶部添加命名空间引用才能识别:
@using Microsoft.AspNetCore.Components.Forms <div class="form-group row"> <label for="name">Contact: </label> <InputText id="name" Value="@Contact.Name" ValueChanged="NameChanged" ValueExpression="() => Contact.Name" ></InputText> </div> @code { private Contact Contact = new(); private void NameChanged(string value) { Contact.Name = value; } public class Contact { public string Name { get; set; } = string.Empty; } }
方案一:纯C#实现节流(推荐,无需额外JS)
利用Timer实现,每次输入时重置计时器,停止输入后计时器到期再执行业务逻辑,完全在Blazor框架内完成:
<input class="form-control form-control-sm" type="number" step="any" @bind-value="Cyclone.CycloneSize" @oninput="HandleInput" /> @code { private Timer? _throttleTimer; // 设置节流延迟,比如1秒(1000毫秒) private const int ThrottleDelayMs = 1000; public class Cyclon { public int CycloneSize { get; set; } = 10; } public Cyclon Cyclone = new(); private void HandleInput(ChangeEventArgs args) { // 每次输入触发时,先销毁之前的计时器 _throttleTimer?.Dispose(); // 创建新计时器,延迟指定时间后触发业务方法 _throttleTimer = new Timer(_ => { // 切换到Blazor主线程执行UI相关逻辑 InvokeAsync(() => CalculateStandardDimensions(args)); }, null, ThrottleDelayMs, Timeout.Infinite); } private void CalculateStandardDimensions(ChangeEventArgs args) { // 这里编写你的业务逻辑 System.Console.WriteLine($"节流触发,当前值:{Cyclone.CycloneSize}"); // 执行完成后清理计时器 _throttleTimer?.Dispose(); _throttleTimer = null; } // 组件销毁时务必清理计时器,避免内存泄漏 public void Dispose() { _throttleTimer?.Dispose(); } }
方案二:使用JavaScript实现节流
如果你更习惯前端节流逻辑,可以通过Blazor的JS互操作实现:
- 在
wwwroot目录下创建throttle.js文件:
let timeoutId; // 节流函数:延迟执行传入的回调 export function throttleInput(callback, delay) { clearTimeout(timeoutId); timeoutId = setTimeout(() => { callback(); }, delay); }
- 在Blazor组件中引用并使用:
@inject IJSRuntime JSRuntime @implements IAsyncDisposable <input class="form-control form-control-sm" type="number" step="any" @bind-value="Cyclone.CycloneSize" @oninput="HandleInputWithJs" /> @code { private IJSObjectReference? _jsModule; private const int ThrottleDelayMs = 1000; public class Cyclon { public int CycloneSize { get; set; } = 10; } public Cyclon Cyclone = new(); protected override async Task OnInitializedAsync() { // 导入JS模块 _jsModule = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./throttle.js"); } private async Task HandleInputWithJs() { // 调用JS节流函数,传入要延迟执行的Blazor方法 await _jsModule.InvokeVoidAsync("throttleInput", DotNetObjectReference.Create(this).InvokeAsync<object>(nameof(CalculateStandardDimensions)), ThrottleDelayMs); } // 标记为可被JS调用的方法 [JSInvokable] public void CalculateStandardDimensions() { System.Console.WriteLine($"JS节流触发,当前值:{Cyclone.CycloneSize}"); } // 组件销毁时清理JS模块 public async ValueTask DisposeAsync() { if (_jsModule != null) { await _jsModule.DisposeAsync(); } } }
内容的提问来源于stack exchange,提问作者Rod
相关产品推荐
相关产品推荐

