C#Blazor:如何使用e.preventDefault()来防止输入中的特定键



这个问题看起来很简单,但我还没有找到任何解决方案。我有一个带有onkeydown事件的Blazor输入:

<input @onkeydown="@(e => KeyWasPressed(e))" 
@onkeydown:preventDefault="@PreventDefault" 
id="@GetId()" 
name="@GetId()" 
@bind-value="@InputValue" 
@bind-value:event="oninput" />

用户应该编写文本,但使用箭头键,用户应该在列表中导航(所以我试图防止光标移动到文本的顶部和末尾(。

在JavaScript中,这可能是这样的:

function KeyWasPressed(e)
{
// key down
if (e.keyCode == 40)
{
e.preventDefault();
// some work...
}
// key up
else if (e.keyCode == 38)
{
e.preventDefault();
// some work...
}
}

如何在Blazor做到这一点?使用@onkeydown:preventDefault,可以防止整个输入。如果将其设置为变量(@PreventDefault(,则只能阻止下一个输入(因为第一个输入已经发生(。只是为了理解我的意思:

  • PreventDefault FALSE>输入"H">将PreventDefault设置为FALSE
  • PreventDefault FALSE>输入"ArrowUp">将PreventDefault设置为TRUE
  • PreventDefaultTRUE>输入"i">将PreventDefault设置为FALSE

因此输入将为(|=光标(:H|>|H>|H

这意味着游标是错误的,"i"被阻止了。

有什么想法吗?谢谢你的建议。

不幸的是,目前还没有简单的解决方案。对于这种情况,如果您想回调.NET代码,您仍然需要使用JS事件处理程序,可能还需要一些互操作。

您可以在这里找到Steve Sanderson关于原因(异步处理程序(的简短评论https://github.com/dotnet/aspnetcore/issues/14517#issuecomment-559184498

另一种解决方法是将输入绑定到变量并手动更新值。(这里也指出了PreventDefault对Blazor的输入(但这可能是一条崎岖的道路。

就我个人而言,我希望看到preventDefault和stopPropagation作为传递到C#方法处理程序的EventArgs的一部分。我认为这在技术上具有挑战性。然而,它将简化许多用例。您可能想在aspnetcore上对此打开一个问题。

(晚了几年,但这可能会帮助其他人。(

drocha87指出此方法仅适用于WebAssembly(wasm(

onkeydown甚至在默认值之前启动,因此我们可以在使用@onkeydown:preventDefault=true.之前立即禁用它。

注:

<input @onkeydown="KeyWasPressed"  @onkeydown:preventDefault="preventDefault" @bind-value="@InputValue" />
@code  {
bool preventDefault = false;
string InputValue = "";
private void KeyWasPressed(KeyboardEventArgs e)
{
// key down
if (e.Key == "ArrowDown")
{
preventDefault = true;
// some work...
}
// key up
else if (e.Key == "ArrowUp")
{
preventDefault = true;
// some work...
}
else 
{
preventDefault = false;
}
}  
}

我的解决方案如下。

在JS中创建以下方法。它将捕捉向上和向下按键。

<script>
function subscribeToChange(componentRef, inputRef) {
console.log("subscribeToChange!");
inputRef.onkeydown = function (event) {
if (event.keyCode == "38") {
event.preventDefault();
console.log("Up key pressed");
componentRef.invokeMethodAsync('invokeFromJS');
}
else if (event.keyCode == "40") {
event.preventDefault();
console.log("Down key pressed");
componentRef.invokeMethodAsync('invokeFromJS');
}
};
inputRef.onkeyup = function (event) {
componentRef.invokeMethodAsync('setValueFromJS', inputRef.value);
};
}
</script>

剃须刀:

<input @ref="Typing3" />
@HelloFromJSStr

剃须刀中:

public ElementReference Typing3;
public string HelloFromJSStr = "";
[JSInvokable("invokeFromJS")]
public async Task HelloFromJS()
{
//HelloFromJSStr += "A";
//StateHasChanged();
// do something here on UP or DOWN button presses..
}
[JSInvokable("setValueFromJS")]
public async Task SetValueFromJS(string newValue)
{
HelloFromJSStr = newValue;
StateHasChanged();
}

在我的例子中,有两种方法。触发onkeyup的一个可以用于设置属性(HelloFromJSStr(的最终值。如果任何其他UI元素需要重新渲染,则随后调用StateHasChanged()方法,如示例所示。休息取决于你的想象。

剩下的代码部分是初始化:

public partial class EventsAndRendering
{
[Inject]
protected IJSRuntime JSRuntime { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
Console.WriteLine($"{this.GetType().Name}: OnAfterRenderAsync. firstRender: {firstRender}");
if (firstRender)
{
var componentRef = DotNetObjectReference.Create(this);
await JSRuntime.InvokeAsync<object>("subscribeToChange", new object[] { componentRef, Typing3 });
}
}
// HelloFromJS()
// SetValueFromJS(string newValue)
}

DotNetObjectReference允许我们从JS中调用C#代码,而不需要使方法statics.

因此,最终流程如下:

  1. 在页面第一次呈现后->我们创建了对主要组件的引用以及对inpout元素的引用
  2. 然后,我们使用上面提到的引用来调用subscribeToChangeJS方法,该方法订阅在我们的输入元素上发生的事件
  3. 在一个keydown事件中,我们触发C#中的方法HelloFromJS
  4. 在一个keyup事件中,我们触发C#中的方法SetValueFromJS

以上只是一个例子,必须根据需要进行调整:(

灵感:https://learn.microsoft.com/en-us/aspnet/core/blazor/call-dotnet-from-javascript?view=aspnetcore-5.0#实例方法调用

编辑:考虑实现IDisposable接口来处理.Net对象:

public void Dispose()
{
componentRef?.Dispose();
}

相关内容

  • 没有找到相关文章

最新更新