Blazor-绑定到由另一个组件更改的服务属性 [英] Blazor - Bind to a property of a service, changed by another component

查看:33
本文介绍了Blazor-绑定到由另一个组件更改的服务属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新(解决方案)

多亏了Magoo先生的回答,我让它正常工作了。该解决方案是通过事件完成的,在官方示例项目FlightFinder中也显示了该解决方案。

请确保使用singleton

示例:Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<LoginService, ILoginService>();
}

LoginService.cs:

public event Action OnChange;
public async Task<bool> LoginFromLocalStorageAsync()
{
    var response = await _http.PostJsonAsync<TokenResult>("/api/auth", model);
    Token = response.Token;
    ExpireDate = response.ExpireDate;
    _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
    OnChange?.Invoke(); // Here we invoke the event
}

NavMenu.cshtml:

protected override void OnInit()
{
    LoginService.OnChange += StateHasChanged;
}

初始问题

我目前正在尝试学习Blazor。我有一个NavMenu组件,它有多个链接,其中之一是:<a href="login">Login</a>,只要用户登录,它就应该更改为<a onclick="@Logout">Logout</a>。使用我自己的服务LoginService在另一个组件(Login组件)中登录。

LoginService具有承载令牌的Token属性和属性public bool IsLoggedIn => !string.IsNullOrEmpty(Token);。我尝试在razor视图中使用带有if-else-语句的简单绑定。这不起作用,我的下一次尝试是在Login组件中使用StateHasChanged();,只要有人登录。也不起作用(可能是因为我想更新NavMenu而不是Login.)

NavMenu.cshtml:

@inject ILoginService LoginService 
@if(LoginService.IsLoggedIn) {
    <a href="logout">Logout</a>
}
else {
    <a href="login">Login</a>
}

Login.cshtml:

<form onsubmit="@Submit">
    <input type="email" placeholder="Email Address" bind="@LoginViewModel.Email" />
    <input type="password" placeholder="Password" bind="@LoginViewModel.Password" />
    <button type="submit">Login</button>
</form>

@functions
{
    public LoginViewModel LoginViewModel { get; } = new LoginViewModel();
    public async Task Submit()
    {
        await LoginService.LoginAsync(LoginViewModel);
    }
}

LoginService.cs

public class LoginService : ILoginService
{
    private readonly HttpClient _http;
    public LoginService(HttpClient http) => _http = http;
    public string Token { get; private set; }
    public bool IsLoggedIn => !string.IsNullOrEmpty(Token);
    public async Task<bool> LoginAsync(LoginViewModel model)
    {
        try
        {
            var response = await _http.PostJsonAsync<TokenResult>("/api/auth", model);
            Token = response.Token;
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
}
不幸的是,NavMenu停留在<a href="login">Login</a>上。我正在考虑从Login组件向NavMenu发送消息。如何使NavMenu更新其视图?

推荐答案

您可以向LoginService添加事件,只要令牌更改就会引发该事件。

然后您的菜单组件可以订阅该事件(您已经注入了LoginService)并调用StateHasChanged()。

这将刷新视图并更新客户端。

这篇关于Blazor-绑定到由另一个组件更改的服务属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆