我是 Blazor(以及一般的 Web 开发人员)的新手。我跟着Microsoft 的 Blazor Web 应用程序待办事项列表教程,在完成上述教程后,我想进一步在每个列表元素旁边添加按钮以将它们从列表中删除。这是我为实现这一目标而编写的代码:
@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>
添加此按钮,但这会引入一个错误。正如我通过发现这个堆栈溢出答案,为了修复这个错误(并允许应用程序构建),我必须更改:
<button @onclick="RemoveTodo(todo)">Remove</button>
包含一个 lambda 函数,如下所示:
<button @onclick="() => RemoveTodo(todo)">Remove</button>
我知道这个更改是有效的,因为我测试了它并且应用程序的行为符合我的预期!但是我要why这个改变有效。
我找到了这个额外的堆栈溢出问题,其中所选答案解释了为了以上述方式将值传递给 @onclick 调用的方法,必须使用 lambda 表达式。答案说使用@onclick
将导致编译器创建一个 EventCallback 对象来处理我提供给的代码@onclick
.
但是,我仍然不明白为什么我的原始代码不起作用。我假设当将值传递给正在执行的函数时,由 EventCallback 对象生成的委托无法正确执行。第二个问题表明,通过 lambda 函数调用会产生一种不同类型的委托,它could解析传递给函数的值。
我对正在发生的事情的理解是否接近事实?为什么我需要以这种方式将函数封装在 lambda 函数中,但仅当所述函数被传递值时才需要?