更好的范围服务实现:
public class CurrentPage
{
public string CurrentPageName { get; private set; }
public void SetCurrentPageName(string name)
{
if (!string.Equals(CurrentPageName, name))
{
CurrentPageName = name;
NotifyStateChanged();
}
}
public event Action OnChange; // event raised when changed
private void NotifyStateChanged() => OnChange?.Invoke();
}
我们不是在传递对象的字典,我们有一个做一件事的简单服务。更改页面的唯一方法是调用SetCurrentPageName,它会引发一个事件让消费者知道名称已更改。这在非嵌套组件之间是必需的,因为否则更新不会传播。
我们还需要在启动时注册服务(因为当前页面是特定于会话的):
services.AddScoped<CurrentPage>();
我们将注入Index.razor,并使用它:
@page "/"
@inject CurrentPage currentPage
<h1>Hello, world!</h1>
Welcome to your new app.
<button @onclick="ChangeName">Set Page Name</button>
<SurveyPrompt Title="How is Blazor working for you?" />
@code
{
protected override void OnInitialized()
{
currentPage.SetCurrentPageName("The Home Page");
base.OnInitialized();
}
void ChangeName() => currentPage.SetCurrentPageName("Name changed");
}
最后在NavMenu.razor的顶部:
@inject CurrentPage currentPage
再往下走。。
<p>The current page is @currentPage.CurrentPageName</p>
@code {
protected override void OnInitialized()
{
// if the OnChange event is raised, refresh this view
currentPage.OnChange += () => StateHasChanged();
base.OnInitialized();
}
这个状态类对它的使用方式一无所知,也没有传递任何对象或引用。
[编辑] 我决定设置页面名称的注入/覆盖模式相当 unBlazor,所以我还编写了一个组件来简化这一点 - PageName.razor:
@inject CurrentPage currentPage;
@code {
[Parameter]
public string Name { get; set; }
protected override void OnParametersSet()
{
currentPage.SetCurrentPageName(Name);
}
}
现在任何想要设置标题的页面都可以这样做:
@page "/fetchdata"
@inject HttpClient Http
<PageName Name="Weather forecast page!" />
整个消费者现在是一个组件:)