【问题标题】:How does ElementReference in Blazor work?Blazor 中的 ElementReference 如何工作?
【发布时间】:2021-05-10 10:32:16
【问题描述】:

我正在构建一个基于输入进行过滤的下拉列表。当您单击向下箭头时,它应该关注列表中的第一项。以下是我遇到的问题的简化版本。

当您在输入中输入“a”然后删除它,然后按向下箭头时,我得到:给定的键不在字典中。有人可以解释为什么会发生这种情况吗?为什么键不在字典中?是什么阻止了它被添加?

<div class="parent" >
<div class="container">
    <input class="input" @oninput="FilterIdentifiers" @onkeydown="(e) => HandleKBEvents(e)"/>
    <div class="dropdown">
        @{
            int i = 1;
            
            foreach (var identifier in identifiersUI)
            {
                <div class="dropdown-item" @key="identifier" tabindex="@i" @ref="refs[identifier]">@identifier</div>

                i++;
            }
        }


    </div>
</div>
@code {
private List<string> identifiers = new List<string>
{
    "Aaa",
    "Aab",
    "Aba",
    "Aca",
    "Baa",
    "Bba"
};

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

private Dictionary<string, ElementReference> refs = new Dictionary<string, ElementReference>();

protected override async Task OnInitializedAsync()
{
    identifiersUI = identifiers;
}

private void FilterIdentifiers(ChangeEventArgs e)
{
    string input = e.Value.ToString();
    refs.Clear();
    identifiersUI = identifiers.Where(s => s.ToUpper().StartsWith(input.ToUpper())).ToList();
    
}

private void HandleKBEvents(KeyboardEventArgs e)
{
    if (e.Code == "ArrowDown")
    {
        refs[identifiersUI[0]].FocusAsync();

    }
}
}

当我将 FilterIdentifiers 方法更改为此时,它确实可以工作。我看到了这个GitHub Blazor @ref,我想我会尝试只删除被过滤掉的键,看看这是否有任何区别......它确实有效。不太明白为什么...

private void FilterIdentifiers(ChangeEventArgs e)
{
    string input = e.Value.ToString();
    var id = identifiers.Where(s => s.ToUpper().StartsWith(input.ToUpper())).ToList();

    //remove removed elements from refs
    var elements = identifiersUI.Except(id);
    identifiersUI = id;

    foreach (var element in elements)
    {
        refs.Remove(element);
    }
}

【问题讨论】:

    标签: c# dictionary blazor ref


    【解决方案1】:

    只需删除 refs.Clear() 并让 Blazor UI 管理 refs

    private void FilterIdentifiers(ChangeEventArgs e)
    {
       string input = e.Value.ToString();
       //refs.Clear();
    identifiersUI = identifiers.Where(s => s.ToUpper().StartsWith(input.ToUpper())).ToList();
    }
    

    当您将@ref 与 HTML 元素而不是 Component 对象一起使用时,会发生很多事情。当您手动清除 refs 时,在下一个渲染事件中,Blazor 仍然认为它们在那里,因此不再添加它们。过滤掉 a 会删除第一个值,因此会出现错误。如果放入断点,您会发现refs 中只有两个元素,即 b。过滤 b 并且所有似乎都有效,但实际上 refs 中只有四个元素 - 只有 a 存在。

    【讨论】:

      【解决方案2】:

      我会说这是因为整个字典都被清除了。 而且我认为您希望 Blazor 每次重置 identifiersUI 列表时“重新构建”该字典,同时循环遍历它以重绘。

      但是 Blazor 的更改跟踪可能决定(并且理所当然地)这些元素没有改变,并没有改变它们。它尤其会跟踪您的下拉项目,特别注意不要过多地摆弄那些identifier 没有改变的元素,因为您已经设置了the @key attribute

      【讨论】:

        猜你喜欢
        • 2021-07-04
        • 1970-01-01
        • 2019-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-16
        相关资源
        最近更新 更多