Blazor 中的 ElementReference 如何工作?
How does ElementReference in Blazor work?
我正在构建一个根据输入进行过滤的下拉列表。当您单击向下箭头时,它应该聚焦于列表中的第一项。以下是我遇到的问题的简化版本。
当您在输入中输入“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);
}
}
我会说这是因为整个字典都被清除了。
而且我假设您希望 Blazor 每次重置 identifiersUI
列表时都“重新构建”该字典,同时循环它以重绘。
但 Blazor 的更改跟踪可能决定(并且理所当然地)这些元素没有改变并保持不变。它特别跟踪你的下拉项目,特别注意不要 fiddle 太多那些 identifier
没有改变的元素,因为你已经设置了 the @key attribute.
只需删除 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 存在。
我正在构建一个根据输入进行过滤的下拉列表。当您单击向下箭头时,它应该聚焦于列表中的第一项。以下是我遇到的问题的简化版本。
当您在输入中输入“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);
}
}
我会说这是因为整个字典都被清除了。
而且我假设您希望 Blazor 每次重置 identifiersUI
列表时都“重新构建”该字典,同时循环它以重绘。
但 Blazor 的更改跟踪可能决定(并且理所当然地)这些元素没有改变并保持不变。它特别跟踪你的下拉项目,特别注意不要 fiddle 太多那些 identifier
没有改变的元素,因为你已经设置了 the @key attribute.
只需删除 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 存在。