asp.net 为什么onkeydown的功能与onclick不同?

z9gpfhce  于 2023-03-04  发布在  .NET
关注(0)|答案(2)|浏览(134)

这是我第一次使用Blazor,所以如果这听起来很愚蠢的话,我道歉。下面是我写的一些Blazor代码:

<ul>
@foreach (var tag in tags)
    {
        <li>
            @tag
            <button class="btn btn-primary" @onclick="() => remove(tag)">remove</button>
        </li>
    }
</ul>

<PageTitle>Home</PageTitle>

<h1>Tags</h1>

<input placeholder="Enter tag" @bind=@tag @onkeydown="enter"/>
<button class="btn btn-primary" @onclick="addTag">Add</button>
<button class="btn btn-primary" @onclick="clear">Clear</button>

@code {
    private string tag;

    private List<string> tags = new List<string>();

    private void addTag()
    {
        if (tags.Count() < 5)
        {
            tags.Add(tag);
            tag = string.Empty;
        }
    }
    private void enter(KeyboardEventArgs e)
    {
        if (e.Code == "Enter")
        {
            addTag();
        }
    }
    private void clear()
    {
        tags.Clear();
    }
    private void remove(string tag)
    {
        tags.Remove(tag);
    }
}

出于某种原因,我不能弄清楚,我期望当添加按钮被单击,或按下回车键时,行为应该是相同的,即,在文本框中输入的输入将被存储在@tag中,并添加到标记列表中。这确实是当添加按钮被单击时发生的事情,但当回车键被按下时,标签列表中的第一个标签总是一个空字符串,然后打开,它被关闭一个。例如:
如果我把mango放在输入框中并按回车键,屏幕上弹出的第一个<li>项是“",如果我把apple放在输入框中并按回车键,屏幕上弹出的下一个<li>项是mango。
差了一分,就我这辈子而言,我也想不出为什么。

brc7rcf0

brc7rcf01#

问题是默认情况下,@bind属性在输入控件上触发change事件时更新值。当您在输入框中按enter键时,onkeydown事件将在change事件之前触发,因此tag字段的值不会更改。要保持值最新,您可以执行以下操作:

<input placeholder="Enter tag" @bind=@tag @bind:event="oninput" @onkeydown="enter"/>

您也可以尝试keyup事件,因为它是在change事件之后触发的:

<input placeholder="Enter tag" @bind=@tag @onkeyup="enter"/>

ASP.NET Core Blazor data binding

bzzcjhmw

bzzcjhmw2#

您的问题是由于事件执行的顺序而发生的。
如果添加以下代码,您将看到tag正在设置。

<div class="alert alert-info">
    Tag: @tag
</div>

在当前设置中:
1.输入连接到onchanged事件(通过@bind连接)。
1.当输入失去焦点(单击其他地方)或单击Enter时,它会更新tag
但是onkeydown事件发生在你按回车键的时候,也就是在onchanged事件之前。此时tag包含的是旧值,它还没有被更新。
您可以通过手动连接输入并在oninput事件而不是onchange事件上触发tag更新来更改事件序列。注意我还将OnEnter移动到onkeyup事件以确保它最后被调用(您永远无法确定不同的浏览器如何实现这些事件)。
以下是您的输入:

  • 版本1 - Net6.0或更早版本 *
<input placeholder="Enter tag" value="@this.tag" @onkeyup=this.OnEnter @oninput=this.OnInput />
  • 版本2 - Net7.0*
<input placeholder="Enter tag" @bind:get=this.tag @bind:event="oninput" @bind:set=this.OnSet @onkeyup=this.OnEnter />

和UI事件处理程序。

private void OnEnter(KeyboardEventArgs e)
    {
        if (e.Code == "Enter")
            addTag();
    }

    private void OnInput(ChangeEventArgs e)
        => tag = e.Value?.ToString() ?? string.Empty;
        
    private void OnSet(string value)
        => tag = value;

事件现在按正确的顺序触发。
下面是我的完整演示页面:

@page "/"

<PageTitle>Index</PageTitle>
<ul>
    @foreach (var tag in tags)
    {
        <li>
            @tag
            <button class="btn btn-primary" @onclick="() => remove(tag)">remove</button>
        </li>
    }
</ul>

<PageTitle>Home</PageTitle>

<h1>Tags</h1>

<input placeholder="Enter tag" value="@this.tag" @onkeyup=this.OnEnter @oninput=this.OnInput />
<button class="btn btn-primary" @onclick="addTag">Add</button>
<button class="btn btn-primary" @onclick="clear">Clear</button>

<div>
    <input placeholder="Enter tag" @bind:get=this.tag @bind:event="oninput" @bind:set=this.OnSet @onkeyup=this.OnEnter />
</div>

<div class="alert alert-info">
    Tag: @tag
</div>

@code {
    private string tag;

    private List<string> tags = new List<string>();

    private void addTag()
    {
        if (tags.Count() < 5)
        {
            tags.Add(tag);
            tag = string.Empty;
        }
    }

    private void OnEnter(KeyboardEventArgs e)
    {
        if (e.Code == "Enter")
            addTag();
    }

    private void OnInput(ChangeEventArgs e)
        => tag = e.Value?.ToString() ?? string.Empty;

    private void OnSet(string value)
        => tag = value;

    private void clear()
    {
        tags.Clear();
    }
    private void remove(string tag)
    {
        tags.Remove(tag);
    }
}

相关问题