更改 blazor 菜单中导航项的可见性
Change visibility of nav item in blazor menu
我将 Blazor 与 .NET Core 3.0 结合使用。
当用户尚未登录时,我想在我的菜单中显示登录信息。当他登录时,登录导航项应该被隐藏。我该怎么做?
编辑:
我使用异步任务更改了 OnInitializedAsync 方法,但这不是问题所在。对于第一次加载,它工作正常。但是然后我转到登录页面,登录并通过 NavigationManager 导航到主页,菜单将不会 "refreshed"。我该如何解决?
以下代码无效...
<div>
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</li>
@if (!_isLoggedIn)
{
<li class="nav-item px-3">
<NavLink class="nav-link" href="login">
<span class="oi oi-person" aria-hidden="true"></span> <LocalizedString Key="NavMenuLogin" />
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="licenseedit">
<span class="oi oi-spreadsheet" aria-hidden="true"></span> <LocalizedString Key="NavMenuRegistration" />
</NavLink>
</li>
}
</ul>
</div>
@code{
private bool _isLoggedIn;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await TokenExistAsync();
}
private async Task TokenExistAsync()
{
var retVal = await Http.GetStringAsync("api/Login/ExistToken");
_isLoggedIn = retVal == "yes";
}
}
我稍微修改了您的代码...使用 Task 而不是 void。
试试这个代码片段:
@code{
private string _loginVisibility = "visible";
protected override async Task OnInitializedAsync()
{
await TokenExistAsync();
}
private async Task TokenExistAsync()
{
var retVal = await Http.GetStringAsync("api/Login/ExistToken");
if (retVal == "yes")
{
_loginVisibility = "hidden";
}
}
}
如果此更改不起作用,请检查您的 CSS 类
注意:我认为使用字符串值来隐藏或显示 li 元素是错误的。您不必隐藏 li 元素。它根本不应该被渲染。你可以像这样定义一个布尔变量:
public bool ShowLink {get; set;} = true;
如您所见,属性 设置为默认值 true,因此呈现 li 元素:
@if ( ShowLink )
{
<li class="nav-item px-3">
<NavLink class="nav-link" href="login">
<span class="oi oi-person" aria-hidden="true"></span>
Login
</NavLink>
</li>
}
并且在 TokenExistAsync 方法中,如果此方法 returns "yes",则应将其设置为 false。因此 li 元素未呈现。
你有
protected override async void OnInitialized()
做到这一点
protected override async Task OnInitializedAsync()
几乎总是避免async void
。在这种情况下,您的应用程序可以 运行 在 TokenExistAsync() 完成之前更新 UI 的逻辑。 void
版本不适合异步使用,名称仅供参考。
此外,Blazor 还特别支持 hidden
和类似的 on/off 属性。您可以使用:
<li class="nav-item px-3" hidden="@hideLogin">
使用相反的逻辑,您需要 ()
,如 hidden=@(!showLogin)
在你的代码块中:
bool hideLogin = false;
...
// _loginVisibility = "hidden";
hideLogin = true;
I changed my code above, but still not working
我想我明白你想要什么...下面是实现它的代码,前提是我是对的...你想刷新嵌入在 MainLayout 中的 NavMenu 组件的内容组件,来自登录页面,对吗?
您可以使用多种方法来实现这一点。以下解决方案基于应用程序状态模式。
首先,我们必须创建一个服务 class,它可以从 NavMenu 组件和 Login 组件访问。这是 class:
public class AppState
{
private bool _loggedIn;
public event Action OnChange;
public bool LoggedIn
{
get { return _loggedIn; }
set {
if (_loggedIn != value)
{
_loggedIn = value;
NotifyStateChanged();
}
}
}
private void NotifyStateChanged() => OnChange?.Invoke();
}
这个 class 定义了一个名为 OnChange 的事件委托,它应该封装将刷新 NavMenu 的方法。当布尔值 属性 LoggedIn 的值更改时调用此委托。 LoggedIn 属性 的值可能会在登录页面中发生变化,当用户已登录时,因此该委托的任何订阅者(在我们的示例中为 NavMenu)都将收到通知。
登录页面
@inject AppState AppState
注意上面将 AppState 注入登录页面。放在页面顶部
AppState.LoggedIn = true;
该代码应放在登录过程的末尾。这将启动 OnChange 委托的触发。
NavMenu 组件
@inject AppState AppState
@implements IDisposable
*
protected override void OnInitialized()
{
AppState.OnChange += StateHasChanged;
}
public void Dispose()
{
AppState.OnChange -= StateHasChanged;
}
现在,无论何时您登录,AppState 服务都会通知 NavMenu 组件重新呈现,以便登录 link 不可见(未呈现)
启动class
services.AddSingleton<AppState>();
我想我知道问题出在哪里了。上面的代码很好并且可以工作。可能的问题可能在登录页面。在类似 navigationManager.NavigateTo("/client/home") 的情况下,NavMenu 代码将不会命中。为此,您应该使用第二个参数:navigationManager.NavigateTo("/client/home", true);
我希望这会有所帮助。
我将 Blazor 与 .NET Core 3.0 结合使用。 当用户尚未登录时,我想在我的菜单中显示登录信息。当他登录时,登录导航项应该被隐藏。我该怎么做?
编辑: 我使用异步任务更改了 OnInitializedAsync 方法,但这不是问题所在。对于第一次加载,它工作正常。但是然后我转到登录页面,登录并通过 NavigationManager 导航到主页,菜单将不会 "refreshed"。我该如何解决?
以下代码无效...
<div>
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</li>
@if (!_isLoggedIn)
{
<li class="nav-item px-3">
<NavLink class="nav-link" href="login">
<span class="oi oi-person" aria-hidden="true"></span> <LocalizedString Key="NavMenuLogin" />
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="licenseedit">
<span class="oi oi-spreadsheet" aria-hidden="true"></span> <LocalizedString Key="NavMenuRegistration" />
</NavLink>
</li>
}
</ul>
</div>
@code{
private bool _isLoggedIn;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
await TokenExistAsync();
}
private async Task TokenExistAsync()
{
var retVal = await Http.GetStringAsync("api/Login/ExistToken");
_isLoggedIn = retVal == "yes";
}
}
我稍微修改了您的代码...使用 Task 而不是 void。 试试这个代码片段:
@code{
private string _loginVisibility = "visible";
protected override async Task OnInitializedAsync()
{
await TokenExistAsync();
}
private async Task TokenExistAsync()
{
var retVal = await Http.GetStringAsync("api/Login/ExistToken");
if (retVal == "yes")
{
_loginVisibility = "hidden";
}
}
}
如果此更改不起作用,请检查您的 CSS 类
注意:我认为使用字符串值来隐藏或显示 li 元素是错误的。您不必隐藏 li 元素。它根本不应该被渲染。你可以像这样定义一个布尔变量:
public bool ShowLink {get; set;} = true;
如您所见,属性 设置为默认值 true,因此呈现 li 元素:
@if ( ShowLink )
{
<li class="nav-item px-3">
<NavLink class="nav-link" href="login">
<span class="oi oi-person" aria-hidden="true"></span>
Login
</NavLink>
</li>
}
并且在 TokenExistAsync 方法中,如果此方法 returns "yes",则应将其设置为 false。因此 li 元素未呈现。
你有
protected override async void OnInitialized()
做到这一点
protected override async Task OnInitializedAsync()
几乎总是避免async void
。在这种情况下,您的应用程序可以 运行 在 TokenExistAsync() 完成之前更新 UI 的逻辑。 void
版本不适合异步使用,名称仅供参考。
此外,Blazor 还特别支持 hidden
和类似的 on/off 属性。您可以使用:
<li class="nav-item px-3" hidden="@hideLogin">
使用相反的逻辑,您需要 ()
,如 hidden=@(!showLogin)
在你的代码块中:
bool hideLogin = false;
...
// _loginVisibility = "hidden";
hideLogin = true;
I changed my code above, but still not working
我想我明白你想要什么...下面是实现它的代码,前提是我是对的...你想刷新嵌入在 MainLayout 中的 NavMenu 组件的内容组件,来自登录页面,对吗?
您可以使用多种方法来实现这一点。以下解决方案基于应用程序状态模式。
首先,我们必须创建一个服务 class,它可以从 NavMenu 组件和 Login 组件访问。这是 class:
public class AppState
{
private bool _loggedIn;
public event Action OnChange;
public bool LoggedIn
{
get { return _loggedIn; }
set {
if (_loggedIn != value)
{
_loggedIn = value;
NotifyStateChanged();
}
}
}
private void NotifyStateChanged() => OnChange?.Invoke();
}
这个 class 定义了一个名为 OnChange 的事件委托,它应该封装将刷新 NavMenu 的方法。当布尔值 属性 LoggedIn 的值更改时调用此委托。 LoggedIn 属性 的值可能会在登录页面中发生变化,当用户已登录时,因此该委托的任何订阅者(在我们的示例中为 NavMenu)都将收到通知。
登录页面
@inject AppState AppState
注意上面将 AppState 注入登录页面。放在页面顶部AppState.LoggedIn = true;
该代码应放在登录过程的末尾。这将启动 OnChange 委托的触发。
NavMenu 组件
@inject AppState AppState
@implements IDisposable
*
protected override void OnInitialized()
{
AppState.OnChange += StateHasChanged;
}
public void Dispose()
{
AppState.OnChange -= StateHasChanged;
}
现在,无论何时您登录,AppState 服务都会通知 NavMenu 组件重新呈现,以便登录 link 不可见(未呈现)
启动class
services.AddSingleton<AppState>();
我想我知道问题出在哪里了。上面的代码很好并且可以工作。可能的问题可能在登录页面。在类似 navigationManager.NavigateTo("/client/home") 的情况下,NavMenu 代码将不会命中。为此,您应该使用第二个参数:navigationManager.NavigateTo("/client/home", true); 我希望这会有所帮助。