我是 Blazor 的新手(以及一般的 Web 开发人员)。我一直跟着 Microsoft's Blazor web app Todo List tutorial,在完成上述教程后,我想更进一步,在每个列表元素旁边添加按钮以将它们从列表中删除。这是我编写的代码来实现:
@page "/todo"
<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
<ul>
@foreach (var todo in todos)
{
<li>
<input type="checkbox" @bind="todo.IsDone" />
<input @bind="todo.Title" />
<button @onclick="RemoveTodo(todo)">Remove</button>
</li>
}
</ul>
<input placeholder="Something to do" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>
@code {
private List<TodoItem> todos = new();
private string newTodo;
private void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
}
}
private void RemoveTodo(TodoItem item)
{
if (item != null)
{
todos.Remove(item);
}
}
}
我以为我可以从 <button @onclick="AddTodo">Add todo</button>
复制语法来添加此按钮,但这会引入一个错误。正如我通过 this Stack Overflow answer 发现的那样,为了修复这个错误(并允许应用程序构建),我必须更改:
<button @onclick="RemoveTodo(todo)">Remove</button>
像这样包含一个 lambda 函数:
<button @onclick="() => RemoveTodo(todo)">Remove</button>
我知道此更改有效,因为我对其进行了测试,并且该应用的行为符合我的预期!但我想知道为什么这种变化有效。
我发现了这个 additional Stack Overflow question,其中选择的答案解释了为了将值传递给@onclick 以上述方式调用的方法,必须使用 lambda 表达式。答案是使用 @onclick
会导致编译器创建一个 EventCallback 对象来处理我提供给 @onclick
的代码。
然而,我仍然不明白为什么我的原始代码不起作用。我假设当一个值被传递给它正在执行的函数时,由 EventCallback 对象生成的委托无法正确执行。第二个问题表明通过 lambda 函数调用会产生一种不同类型的委托,它可以解析传递给函数的值。
我对正在发生的事情的理解接近真相吗?为什么我需要以这种方式在 lambda 函数内部封装函数,但仅在所述函数被传递值时才需要?
答案 0 :(得分:2)
它是关于 C# 语法的。事件处理程序必须是委托(对方法的引用)。
显示错误的最短方式:
<button @onclick="AddTodo">Add todo</button> // ok
<button @onclick="AddTodo()">Add todo</button> // error
<button @onclick="() => AddTodo()">Add todo</button> // ok
因为,在普通的 C# 中:
delegate x = AddTodo; // ok, a methodname w/o () means "address off"
delegate x = AddTodo(); // error, void is not a delegate
delegate x = () => AddTodo(); // ok, a lambda is a delegate
我们通常更喜欢第一个较短的版本。但是一旦你有一个论点,你就需要长格式。
答案 1 :(得分:1)
如果您将鼠标悬停在任何控件中的 @onclick
(或其他 @events
)上,您将获得有关默认期望的函数的信息:字符串或委托值,如果是委托,则应该是 MouseEventArgs
类型(在本例中)
我不会推测他们为什么以这种或另一种方式做事,但文档显示了在 Blazor 中处理事件的各种方法的示例:
https://docs.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-5.0
IMO,官方文档通常非常好。我通常用谷歌搜索“MSDN BLAZOR ____”来找到我想要的。