导航正在发生之前运行,导航还未发生转向,还未跳转到目标 URL,可在此方法注册的事件处理程序中进行拦截,可阻止导航或进一步转向。 在当前页面上单击链接或通过代码执行 NavigateTo()方法都可以转向目标 URL,但要注意如下事项: (1) 在独立 Blazor WebAssembly 应用程序中,通过单击链接或通过代码执行NavigateTo()方法都可以转向目标 URL,并且都会触发RegisterLocationChangingHandler()方法注册的导航事件。 (2) 在 Blazor WebApp 中,任何呈现模式的交互位置为全局的项目,通过单击链接或代码执行 NavigateTo()方法都可以转向目标 URL,并且都会触发RegisterLocationChangingHandler()方法注册的导航事件。 (3) 在 Blazor WebApp 中,任何呈现模式的交互位置为每页/组件时,单击当前页面上的链接进行转向,不会触发RegisterLocationChangingHandler()方法注册导航事件,而通过NavigateTo()方法是可以触发的。
RegisterLocationChangingHandler()方法,该方法定义如下: RegisterLocationChangingHandler(Func<LocationChangingContext, ValueTask> locationChangingHandler) 传入一个Func<LocationChangingContext,ValueTask> locationChangingHandler 类型的委托
LocationChangingContext 上下文中得到与更改位置相关的信息,如下: (1) TargetLocation 属性:获取目标位置的 URL。 (2) HistoryEntryState 属性:获取与目标历史记录条目关联的状态。 (3) IsNavigationIntercepted 属性:获取在当前页面中,是从单击链接转向目标 URL(为 true),还是使用 NavigateTo()方法以代码方式转向目标URL(为 false)。 (4) PreventNavigation()方法:调用以阻止导航继续。
@page "/demoPage"
@inject NavigationManager NavigationManager
@implements IDisposable
<h3>demoPage</h3>
<a href="/counter">链接转向</a>
<button @onclick="OnClick" >代码转向</button>
@code {
private IDisposable? _disposable;
private void OnClick()
{
NavigationManager.NavigateTo("/counter");
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
_disposable = NavigationManager.RegisterLocationChangingHandler(OnLocationChanging);
}
}
private ValueTask OnLocationChanging(LocationChangingContext context)
{
Console.WriteLine($"目标位置的 URL:{context.TargetLocation}");
Console.WriteLine($"目标历史记录条目关联的状态:{context.HistoryEntryState}");
Console.WriteLine($"IsNavigationIntercepted:{context.IsNavigationIntercepted}");
return ValueTask.CompletedTask;
}
public void Dispose()
{
_disposable?.Dispose();
}
}
● 第一次运行时,在 Navigation.RegisterLocationChangingHandler()方法中注册了 OnLocationChanging 事件处理程序,事件只需要注册一次,所以在首次时进行注册 ● 注册事件处理程序后返回的是 IDisposable 类型,这是非托管资源,需要手动在实现的 Dispose()方法中释放资源
点击代码跳转
点击链接跳转
拦截跳转我们可以使用context.PreventNavigation()方法进行拦截
private ValueTask OnLocationChanging(LocationChangingContext context)
{
if (context.TargetLocation.Contains("counter"))
{
context.PreventNavigation();
}
Console.WriteLine($"目标位置的 URL:{context.TargetLocation}");
Console.WriteLine($"目标历史记录条目关联的状态:{context.HistoryEntryState}");
Console.WriteLine($"IsNavigationIntercepted:{context.IsNavigationIntercepted}");
return ValueTask.CompletedTask;
}
直接在OnLocationChanging
方法中拦截即可
LocationChanged 事件:导航发生转向之后执行,也就是已经跳转到目标URL 了,不可阻止导航。
@page "/demoPage"
@inject NavigationManager NavigationManager
<h3>demoPage</h3>
<button @onclick="OnClick" >代码跳转</button>
@code {
private void OnClick()
{
NavigationManager.NavigateTo("/test", new NavigationOptions()
{
HistoryEntryState = "历史状态1"
});
}
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
NavigationManager.LocationChanged += NavigationManagerOnLocationChanged;
}
}
private void NavigationManagerOnLocationChanged(object? sender, LocationChangedEventArgs e)
{
Console.WriteLine($"目标位置的 URL:{e.Location}");
Console.WriteLine($"目标历史记录条目关联的状态:{ e.HistoryEntryState}");
Console.WriteLine($"IsNavigationIntercepted:{ e.IsNavigationIntercepted}");
}
}
完成跳转并触发了事件
对于 LocationChanged 事件,除了通过代码调用Navigation.NavigateTo()方法导航到目标 URL 后触发,还可以通过单击链接导航到目标 URL 后触发。 我们点击左侧导航进行跳转页面,信息也是可以正常输出的,被成功调用
在 Blazor WebApp 任何呈现模式中,使用后退或前进功能时,LocationChanged 事件会被触发。但是使用 RegisterLocationChangingHandler()方法注册的事件在每页/组件交互位置下是不会被触发。
LocationChanged 事件与 RegisterLocationChangingHandler()方法注册的事件都属于 Blazor WebApp 中组件路由守卫,二者区别如下: 触发时机: (1) RegisterLocationChangingHandler()方法:导航正在发生之前运行,导航还未发生转向,还未跳转到目标 URL,可在此方法注册的事件处理程序中进行拦截,可阻止导航或进一步转向。 (2) LocationChanged 事件:导航发生转向之后执行,也就是已经跳转到目标URL 了,不可阻止导航。 触发条件: (1) LocationChanged 事件可以在任何的 Blazor 项目中通过代码和链接都可以被触发。 (2) RegisterLocationChangingHandler()方法注册的事件在 WebApp 任何呈现模式+每页/组件交互位置项目中链接不可触发,但代码可以触发。