阅读了您的帖子和评论后,我决定编写一些组件,这些组件是我觉得能够回答您的问题并向您展示未来编写Blazor组件的好方法。让我们从第一个组件开始,即StudentSelector.razor:
StudentSelector.razor
@using BlazorAnswers.Models
@*Show loading content while students are loading*@
@if(!StudentList.Any())
{
@LoadingContent
}
else
{
<label>Select a Student: </label>
<select @onchange="HandleStudentChanged" class="form-select w-25">
@foreach (var student in StudentList)
{
<option value="@student.Id">@student.Name</option>
}
</select>
}
@code {
[Parameter] public EventCallback<StudentModel> OnStudentChanged { get; set; }
[Parameter] public IEnumerable<StudentModel> StudentList { get; set; } = Enumerable.Empty<StudentModel>();
[Parameter] public RenderFragment LoadingContent { get; set; }
private async Task HandleStudentChanged(ChangeEventArgs args)
{
if (OnStudentChanged.HasDelegate)
{
if (args is not null && int.TryParse((string)args.Value, out var id))
{
var selectedStudent = StudentList.FirstOrDefault(a => a.Id.Equals(id));
if (selectedStudent is not null)
await OnStudentChanged.InvokeAsync(selectedStudent);
}
}
}
}
下一个组件应该是用于显示选择的学生的组件:
@using BlazorAnswers.Models
@if (SelectedStudent is not null)
{
@StudentContent(SelectedStudent)
}
@code {
[Parameter] public StudentModel? SelectedStudent { get; set; }
[Parameter] public RenderFragment<StudentModel> StudentContent { get; set; } = default!;
}
最后,所有内容都将放在可导航的页面Student.razor中:
Student.razor
@page "/student"
@using BlazorAnswers.Models
<StudentSelector OnStudentChanged="HandleStudentSelected"
StudentList="@_students">
<LoadingContent>
Loading Students...
</LoadingContent>
</StudentSelector>
@if (_selectedStudent is not null)
{
<div class="container-lg pt-4">
<StudentDisplay SelectedStudent="@_selectedStudent">
<StudentContent Context="student">
<p> Displaying profile of Id: @student.Id </p>
<p> Displaying profile of Name: @student.Name </p>
</StudentContent>
</StudentDisplay>
</div>
}
@code {
private StudentModel _selectedStudent;
private IEnumerable<StudentModel> _students = Enumerable.Empty<StudentModel>();
protected override async Task OnInitializedAsync()
{
try
{
await GetStudents();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void HandleStudentSelected(StudentModel selectedStudent)
{
_selectedStudent = selectedStudent;
}
private async Task GetStudents()
{
await Task.Delay(3000);
_students = _selectableStudents;
}
private static IEnumerable<StudentModel> _selectableStudents = new List<StudentModel>()
{
new StudentModel{ Id = 1, Name = "Joe" },
new StudentModel{ Id = 2, Name = "Amy" },
new StudentModel{ Id = 3, Name = "Beth" },
new StudentModel{ Id = 4, Name = "Kevin" },
new StudentModel{ Id = 5, Name = "Carl" },
new StudentModel{ Id = 6, Name = "Chad" },
new StudentModel{ Id = 7, Name = "Bryan" },
new StudentModel{ Id = 8, Name = "Kelly" },
new StudentModel{ Id = 9, Name = "Steve" },
new StudentModel{ Id = 10, Name = "Doug" },
};
}
那么这里是学生模型类:
StudentModel.cs
public class StudentModel
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
设计 Blazor 应用程序时,还有一件事需要考虑,那就是让组件保持简单、页面保持智能。这意味着在注入服务时要尽可能将它们保留在页面中,而不是让它们进入组件本身。这可以避免很多复杂性,并允许您构建可重用的组件。我知道有人提到了调用 StateHasChanged,但请尽量仅在 UI 中的更改源于非人类交互时使用它。![输入图像描述](https://istack.dev59.com/ryOE5.gif)
StateHasChanged()
放置在你的GetStudentId()
函数中,例如在student = _id
之后。 - Roland DeschainStateHasChanged();
放在Student
组件内部不会刷新组件。 - elektra