C# Blazor文本字段Oninput用户键入延迟
如何在Blazor中为事件(OnInput)添加延迟?C# Blazor文本字段Oninput用户键入延迟,c#,throttling,blazor,blazor-server-side,debounce,C#,Throttling,Blazor,Blazor Server Side,Debounce,如何在Blazor中为事件(OnInput)添加延迟?例如,如果用户正在文本字段中键入内容,您希望等待用户完成键入。 Blazor.Templates::3.0.0-preview8.19405.7 代码: @page "/" <input type="text" @bind="Data" @oninput="OnInputHandler"/> <p>@Data</p> @code { public string Data { get; se
例如,如果用户正在文本字段中键入内容,您希望等待用户完成键入。
Blazor.Templates::3.0.0-preview8.19405.7 代码:
@page "/"
<input type="text" @bind="Data" @oninput="OnInputHandler"/>
<p>@Data</p>
@code {
public string Data { get; set; }
public void OnInputHandler(UIChangeEventArgs e)
{
Data = e.Value.ToString();
}
}
@page/“
@资料
@代码{
公共字符串数据{get;set;}
InpAuthHandler上的公共无效(UIChangeEventArgs e)
{
Data=e.Value.ToString();
}
}
解决方案:
你的问题没有单一的解决办法。下面的代码只是一种方法。看一看,并根据您的要求进行调整。代码在每个键控
上重置计时器,只有最后一个计时器引发OnUserFinish
事件。
记住通过实现IDisposable
@using System.Timers;
@implements IDisposable;
...
<input type="text" @bind-value="Data" @bind-value:event="oninput"
@onkeyup="@HandleKeyUp"/>
<p>@Data2</p>
@code {
public string Data { get; set; }
public string Data2 { get; set; }
private Timer aTimer;
protected override void OnInitialized()
{
aTimer = new Timer(1000);
aTimer.Elapsed += OnUserFinish;
aTimer.AutoReset = false;
}
void HandleKeyUp(KeyboardEventArgs e)
{
// remove previous one
aTimer.Stop();
// new timer
aTimer.Start();
}
private void OnUserFinish(Object source, ElapsedEventArgs e)
{
InvokeAsync( () =>
{
Data2 = $"User has finished: {Data}";
StateHasChanged();
});
}
void IDisposable.Dispose()
{
aTimer?.Dispose();
}
}
@使用系统计时器;
@实现可识别性;
...
@数据2
@代码{
公共字符串数据{get;set;}
公共字符串Data2{get;set;}
私人定时器;
受保护的覆盖无效OnInitialized()
{
aTimer=新定时器(1000);
aTimer.appeased+=OnUserFinish;
aTimer.AutoReset=false;
}
无效HandleKeyUp(键盘事件参数e)
{
//删除上一个
停止();
//新定时器
aTimer.Start();
}
私有void OnUserFinish(对象源,ElapsedEventArgs e)
{
InvokeAsync(()=>
{
Data2=$“用户已完成:{Data}”;
StateHasChanged();
});
}
void IDisposable.Dispose()无效
{
aTimer?.Dispose();
}
}
用例:
这段代码的用例的一个例子是避免后端请求,因为在用户停止键入之前不会发送请求
运行:
我已经创建了一组。其中之一是具有多种输入类型和更多功能。Blazor.Components.Debounce.Input在上提供
你可以试试这个
注意:目前正在预览中。最终版本将随.NET5一起发布。发布此答案介于之前的答案之间,即介于和之间 它利用了强大的库(又称Rx),我认为这是在正常情况下解决此类问题的唯一合理方法 解决方案 安装NuGet软件包后,您可以在组件中导入所需的名称空间:
@使用System.Reactive.Subjects
@使用System.Reactive.Linq
在组件上创建一个Subject
字段,作为输入事件和可观察管道之间的粘合剂:
@code{
私有主题searchTerm=new();
// ...
}
将主题
与您的输入连接起来
:
最后,定义可观察的管道:
@code{
// ...
私人物品[]?物品;
受保护的重写异步任务OnInitializedAsync(){
搜索词
.节气门(时间跨度从毫秒(200))
.选择(e=>(字符串?)e.Value)
.Select(v=>v?.Trim())
.DistinctUntilChanged()
.SelectMany(搜索内容)
.订阅(ts=>{
事物=ts;
StateHasChanged();
});
}
私有任务SearchThings(字符串?searchTerm=null)
=>HttpClient.GetFromJsonAsync($“api/things?search={searchTerm}”)
}
上面的示例管道将
- 给用户200毫秒的时间完成输入(也称为取消抖动或限制输入)
- 从
ChangeEventArgs
中选择键入的值
- 修剪它
- 跳过与上一个相同的任何值
- 使用到目前为止的所有值发出HTTP GET请求
- 将响应数据存储在字段
things
中
- 最后告诉组件它需要重新渲染
如果您的标记中有如下内容,则在键入时将看到它被更新:
@foreach(事物中的var thing){
}
附加说明
别忘了打扫卫生
您应该像这样正确地处理事件订阅:
@实现组件顶部的IDisposable//
//加价
@代码{
// ...
私人IDisposable?订阅;
public void Dispose()=>订阅?.Dispose();
受保护的重写异步任务OnInitializedAsync(){
订阅=搜索期限
.节气门(时间跨度从毫秒(200))
// ...
.认购(/*…*/);
}
}
Subscribe()
实际上返回一个IDisposable
,您应该将其与组件一起存储和处置。但不要在其上使用using
,因为这会过早地破坏订阅
开放性问题
有些事情我还没有弄明白:
- 是否可以避免调用
statehaschange()
- 是否可以避免调用
Subscribe()
,并直接绑定到标记内部的可观察的
,就像使用
- 是否可以避免创建
主题
?Rx支持从C#事件
s创建可观察的
s,但是如何获取oninput
事件的C对象
您好,感谢您的回答和解决方案!这正是我想要的,我想我必须添加Javascript:P作为提示,当您使用System.Timers添加@时,此源代码可以工作代码>确保在的dispose方法上处置计时器component@Alexandre哇,谢谢你的建议。你真的很乐意改进答案吗?可以自由编辑。只需查看一下debounce和Throttling,我就发现了:有机会获得.NET Core 3.1版本吗?@akrobet谢谢联系我。我正在使用新的CSS隔离和JS互操作特性。因此,这已经是巨大的努力,以w