Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Замечание
Это не последняя версия этой статьи. В текущей версии см. версию .NET 10 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Для получения дополнительной информации см. Политику поддержки .NET и .NET Core. В текущей версии см. версию .NET 10 этой статьи.
В этой статье объясняется, как активировать и обрабатывать навигацию Blazorпо страницам. Хотя пользователи могут перемещаться между разными страницами с помощью обычных HTML-ссылок, Blazor улучшает навигацию в приложении, чтобы избежать полной перезагрузки страниц и обеспечить более плавное взаимодействие. NavLink Используйте компонент для создания ссылок навигации, которые автоматически применяют стили, когда ссылка соответствует текущей странице. Для программной навигации и управления URI с помощью службы в коде C# используйте NavigationManager.
В этой статье объясняется, как активировать и обрабатывать навигацию Blazorпо страницам. NavLink Используйте компонент для создания ссылок навигации, которые автоматически применяют стили, когда ссылка соответствует текущей странице. Для программной навигации и управления URI в коде NavigationManager C# используйте службу.
Это важно
Примеры кода в этой статье показывают вызовы методов на Navigation, который является инъецированным NavigationManager в классах и компонентах.
Компонент NavLink
Используйте при создании ссылок навигации компонент NavLink вместо HTML-элементов гиперссылок (<a>). Компонент NavLink ведет себя как элемент <a>, за исключением того, что он переключает класс CSS active в зависимости от того, соответствует ли его href текущему URL-адресу. Класс active помогает пользователю понять, какая страница является активной страницей среди отображаемых ссылок навигации. При необходимости назначьте имя класса CSS свойству NavLink.ActiveClass, чтобы применить пользовательский класс CSS к отображаемой ссылке, если текущий маршрут совпадает с href.
В компоненте NavMenu (NavMenu.razor) приложения Blazor, созданного на основе шаблона проекта Blazor:
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
В предыдущем примере HomeNavLinkhref="" совпадает с домашним URL-адресом и получает только класс CSS active по базовому пути приложения по умолчанию (/).
NavLink Второй получает active класс, когда пользователь посещает Counter компонент /counter.
Существует два параметра NavLinkMatch, которые можно назначить атрибуту Match элемента <NavLink>:
-
NavLinkMatch.All: NavLink активна при совпадении с текущим URL-адресом, игнорируя строку запроса и фрагмент. Чтобы включить сопоставление по строке запроса/фрагменту, используйте переключатель
Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContext, установленный наtrue. - NavLinkMatch.Prefix (по умолчанию) NavLink активен, если он соответствует любому префиксу текущего URL-адреса.
Для применения пользовательской логики сопоставления создайте подкласс NavLink и переопределите его метод ShouldMatch. Верните true из метода, если вы хотите применить класс CSS active:
public class CustomNavLink : NavLink
{
protected override bool ShouldMatch(string currentUriAbsolute)
{
// Custom matching logic
}
}
Существует два параметра NavLinkMatch, которые можно назначить атрибуту Match элемента <NavLink>:
- NavLinkMatch.All: NavLink активна при совпадении всего текущего URL-адреса, включая строку запроса и фрагмент.
- NavLinkMatch.Prefix (по умолчанию) NavLink активен, если он соответствует любому префиксу текущего URL-адреса.
Дополнительные атрибуты компонента NavLink передаются в отображаемый тег привязки. В следующем примере компонент NavLink включает атрибут target.
<NavLink href="example-page" target="_blank">Example page</NavLink>
Отобразится следующая разметка HTML.
<a href="example-page" target="_blank">Example page</a>
Предупреждение
В связи с тем, как Blazor выполняет рендеринг дочернего содержимого, для рендеринга компонентов NavLink в цикле for требуется задать локальную переменную индекса, если в содержимом дочернего компонента NavLink используется переменная цикла приращения:
@for (int c = 1; c < 4; c++)
{
var ct = c;
<li ...>
<NavLink ...>
<span ...></span> Product #@ct
</NavLink>
</li>
}
Использование переменной индекса в этом сценарии обязательно для любого дочернего компонента, который использует переменную цикла в своем дочернем содержимом, а не только для компонента NavLink.
Вместо этого можно использовать цикл foreach с Enumerable.Range:
@foreach (var c in Enumerable.Range(1, 3))
{
<li ...>
<NavLink ...>
<span ...></span> Product #@c
</NavLink>
</li>
}
URI и вспомогательные средства для навигации
Используйте NavigationManager для управления кодами URI и навигацией в коде C#. NavigationManager предоставляет события и методы, приведенные в следующей таблице.
| Член | Description |
|---|---|
| Uri | Возвращает текущий абсолютный URI. |
| BaseUri | Получает базовый URI (с завершающим слэшем), который можно присоединить к относительным путям URI для получения абсолютного URI. Как правило, BaseUri соответствует атрибуту href элемента <base> документа (расположение содержимого <head>). |
| NavigateTo | Переходит по указанному URI. Если значение forceLoad равно false:
forceLoad равно true:
Дополнительные сведения см. в разделе "Расширенная навигация и обработка форм". Если |
| LocationChanged | Событие, которое запускается при изменении точки навигации. Дополнительные сведения см. в разделе Изменения расположения. |
NotFound |
Вызывается для обработки сценариев, когда запрошенный ресурс не найден. Дополнительные сведения см. в разделе "Не найдено ответов ". |
| ToAbsoluteUri | Преобразует относительный URI в абсолютный. |
| ToBaseRelativePath | На основе базового URI приложения преобразует абсолютный URI в URI относительно базового URI. Например, см. раздел "Создать URI, относящийся к базовому префиксу URI". |
RegisterLocationChangingHandler |
Регистрирует обработчик для обработки входящих событий навигации. Вызов NavigateTo всегда активирует обработчик. |
| GetUriWithQueryParameter | Возвращает URI, созданный путем обновления NavigationManager.Uri с добавлением, обновлением или удалением одного параметра. Дополнительные сведения см. в разделе Строки запросов. |
| Член | Description |
|---|---|
| Uri | Возвращает текущий абсолютный URI. |
| BaseUri | Получает базовый URI (с завершающим слэшем), который можно присоединить к относительным путям URI для получения абсолютного URI. Как правило, BaseUri соответствует атрибуту href элемента <base> документа (расположение содержимого <head>). |
| NavigateTo | Переходит по указанному URI. Если значение forceLoad равно false:
forceLoad равно true:
Дополнительные сведения см. в разделе "Расширенная навигация и обработка форм". Если |
| LocationChanged | Событие, которое запускается при изменении точки навигации. Дополнительные сведения см. в разделе Изменения расположения. |
| ToAbsoluteUri | Преобразует относительный URI в абсолютный. |
| ToBaseRelativePath | На основе базового URI приложения преобразует абсолютный URI в URI относительно базового URI. Например, см. раздел "Создать URI, относящийся к базовому префиксу URI". |
RegisterLocationChangingHandler |
Регистрирует обработчик для обработки входящих событий навигации. Вызов NavigateTo всегда активирует обработчик. |
| GetUriWithQueryParameter | Возвращает URI, созданный путем обновления NavigationManager.Uri с добавлением, обновлением или удалением одного параметра. Дополнительные сведения см. в разделе Строки запросов. |
| Член | Description |
|---|---|
| Uri | Возвращает текущий абсолютный URI. |
| BaseUri | Получает базовый URI (с завершающим слэшем), который можно присоединить к относительным путям URI для получения абсолютного URI. Как правило, BaseUri соответствует атрибуту href элемента <base> документа (расположение содержимого <head>). |
| NavigateTo | Переходит по указанному URI. Если значение forceLoad равно true:
replace имеет значение true, текущий URI в журнале браузера заменяется вместо отправки нового URI в стек журнала. |
| LocationChanged | Событие, которое запускается при изменении точки навигации. Дополнительные сведения см. в разделе Изменения расположения. |
| ToAbsoluteUri | Преобразует относительный URI в абсолютный. |
| ToBaseRelativePath | На основе базового URI приложения преобразует абсолютный URI в URI относительно базового URI. Например, см. раздел "Создать URI, относящийся к базовому префиксу URI". |
RegisterLocationChangingHandler |
Регистрирует обработчик для обработки входящих событий навигации. Вызов NavigateTo всегда активирует обработчик. |
| GetUriWithQueryParameter | Возвращает URI, созданный путем обновления NavigationManager.Uri с добавлением, обновлением или удалением одного параметра. Дополнительные сведения см. в разделе Строки запросов. |
| Член | Description |
|---|---|
| Uri | Возвращает текущий абсолютный URI. |
| BaseUri | Получает базовый URI (с завершающим слэшем), который можно присоединить к относительным путям URI для получения абсолютного URI. Как правило, BaseUri соответствует атрибуту href элемента <base> документа (расположение содержимого <head>). |
| NavigateTo | Переходит по указанному URI. Если значение forceLoad равно true:
replace имеет значение true, текущий URI в журнале браузера заменяется вместо отправки нового URI в стек журнала. |
| LocationChanged | Событие, которое запускается при изменении точки навигации. Дополнительные сведения см. в разделе Изменения расположения. |
| ToAbsoluteUri | Преобразует относительный URI в абсолютный. |
| ToBaseRelativePath | На основе базового URI приложения преобразует абсолютный URI в URI относительно базового URI. Например, см. раздел "Создать URI, относящийся к базовому префиксу URI". |
| GetUriWithQueryParameter | Возвращает URI, созданный путем обновления NavigationManager.Uri с добавлением, обновлением или удалением одного параметра. Дополнительные сведения см. в разделе Строки запросов. |
| Член | Description |
|---|---|
| Uri | Возвращает текущий абсолютный URI. |
| BaseUri | Получает базовый URI (с завершающим слэшем), который можно присоединить к относительным путям URI для получения абсолютного URI. Как правило, BaseUri соответствует атрибуту href элемента <base> документа (расположение содержимого <head>). |
| NavigateTo | Переходит по указанному URI. Если значение forceLoad равно true:
|
| LocationChanged | Событие, которое запускается при изменении точки навигации. |
| ToAbsoluteUri | Преобразует относительный URI в абсолютный. |
| ToBaseRelativePath | На основе базового URI приложения преобразует абсолютный URI в URI относительно базового URI. Например, см. раздел "Создать URI, относящийся к базовому префиксу URI". |
Изменения расположения
Для события LocationChangedLocationChangedEventArgs предоставляет следующие сведения о событиях навигации.
- Location: URL-адрес нового расположения.
-
IsNavigationIntercepted: если
trueперехватила навигацию в Blazor браузере. Еслиfalse, NavigationManager.NavigateTo вызвал переход.
Следующий компонент:
- переходит к компоненту
Counterприложения (Counter.razor) при нажатии кнопки с помощью NavigateTo; - Обрабатывает событие изменения местоположения путем оформления подписки на NavigationManager.LocationChanged.
Метод
HandleLocationChangedотсоединяется, когда платформа вызываетDispose. Отсоединение метода позволяет выполнить сборку мусора для компонента.При нажатии кнопки реализация средства ведения журнала записывает следующие сведения.
BlazorSample.Pages.Navigate: Information: URL of new location: https://localhost:{PORT}/counter
Navigate.razor:
@page "/navigate"
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation
<h1>Navigate Example</h1>
<button class="btn btn-primary" @onclick="NavigateToCounterComponent">
Navigate to the Counter component
</button>
@code {
private void NavigateToCounterComponent() => Navigation.NavigateTo("counter");
protected override void OnInitialized() =>
Navigation.LocationChanged += HandleLocationChanged;
private void HandleLocationChanged(object? sender, LocationChangedEventArgs e) =>
Logger.LogInformation("URL of new location: {Location}", e.Location);
public void Dispose() => Navigation.LocationChanged -= HandleLocationChanged;
}
Дополнительные сведения об удалении компонентов см. в разделе Удаление компонентов в ASP.NET Core Razor.
Поведение перенаправления диспетчера навигации во время отрисовки на стороне статического сервера (статический SSR)
Для перенаправления во время отрисовки на стороне статического сервера (статический SSR) NavigationManager используется исключение NavigationException , которое захватывается платформой, которая преобразует ошибку в перенаправление. Код, который существует после вызова NavigateTo , не вызывается. При использовании Visual Studio отладчик прерывает исключение, требуя отмены флажка для прерывания, если этот тип исключения обрабатывается пользователем в пользовательском интерфейсе Visual Studio, чтобы избежать остановки отладчика для будущих перенаправлений.
Свойство MSBuild, заданное <BlazorDisableThrowNavigationException> в файле проекта приложения, можно использовать true для того, чтобы больше не вызывать NavigationExceptionисключение. Кроме того, код после вызова NavigateTo выполняется, когда он не будет выполняться раньше. Это поведение включено по умолчанию в шаблоне проекта .NET 10 или более поздней версии Blazor Web App :
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
Замечание
В .NET 10 или более поздней версии вы можете отказаться от создания объекта, задав NavigationException<BlazorDisableThrowNavigationException> для свойства MSBuild значение true в файле проекта приложения. Чтобы воспользоваться новым свойством и поведением MSBuild, обновите приложение до .NET 10 или более поздней версии.
Не найдены ответы
NavigationManager
NotFound предоставляет метод для обработки сценариев, когда запрошенный ресурс не найден во время статического рендеринга на стороне сервера (SSR) или глобального интерактивного рендеринга:
Статический SSR: вызов
NavigationManager.NotFoundустанавливает код состояния HTTP на 404.Интерактивная отрисовка: сигнализирует Blazor маршрутизатору (
Routerкомпоненту) для отрисовки не найденного содержимого.Потоковая отрисовка: если расширенная навигация активна, потоковая отрисовка отрисовывает не найденное содержимое без перезагрузки страницы. Если расширенная навигация заблокирована, платформа перенаправляется на содержимое Not Found с обновлением страницы.
Замечание
В следующем обсуждении упоминается, что компонент Not Found Razor можно назначить в параметр Router компонента NotFoundPage. Этот параметр работает в сочетании с NavigationManager.NotFound и подробно описан далее в этом разделе.
Потоковая отрисовка может отображать только компоненты, имеющие маршрут, например NotFoundPage назначение (NotFoundPage="...") или назначение страницы кода состояния повторного выполнения по промежуточного слоя (UseStatusCodePagesWithReExecute).
DefaultNotFound 404 содержимое ("Not foundобычный текст") не имеет маршрута, поэтому его нельзя использовать во время потоковой отрисовки.
Замечание
Фрагмент отрисовки не найден (<NotFound>...</NotFound>) не поддерживается в .NET 10 или более поздней версии.
NavigationManager.NotFound Рендеринг содержимого использует следующее, независимо от того, начался ли ответ (в порядке):
- Если NotFoundEventArgs.Path задан, отобразите содержимое назначенной страницы.
- Если
Router.NotFoundPageзадан, отобразите назначенную страницу. - При правильной настройке страниц кодов состояния через промежуточное программное обеспечение повторного выполнения.
- Никаких действий, если ни один из предыдущих подходов не принят.
ПО переобработки страниц с кодами состояния имеет UseStatusCodePagesWithReExecute приоритет в решении проблем маршрутизации адресов, связанных с браузером, таких как ввод неправильного URL-адреса в адресную строку браузера или выбор ссылки, не ведущей к конечной точке в приложении.
Когда компонент отображается статически (статический SSR) и NavigationManager.NotFound вызывается, код состояния 404 устанавливается в ответе:
@page "/render-not-found-ssr"
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NotFound();
}
}
Чтобы предоставить содержимое страницы «Не найдено» для глобального интерактивного рендеринга, используйте компонент Razor.
Замечание
Шаблон Blazor проекта содержит страницу NotFound.razor . Эта страница автоматически отрисовывается всякий раз, когда вызывается NavigationManager.NotFound, что позволяет обрабатывать отсутствующие маршруты с единым пользовательским опытом.
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>
Компонент NotFound назначается параметру маршрутизатора NotFoundPage .
NotFoundPage поддерживает маршрутизацию, которую можно использовать в промежуточном слое повторного выполнения страниц кодов состояния, включая промежуточные слои, отличные от Blazor.
В следующем примере предыдущий NotFound компонент присутствует в папке приложения Pages и передается параметру NotFoundPage :
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
</Router>
Когда компонент отрисовывается в глобальном интерактивном режиме, вызов NavigationManager.NotFound сигнализирует маршрутизатору Blazor отрисовать компонент NotFound.
@page "/render-not-found-interactive"
@inject NavigationManager Navigation
@if (RendererInfo.IsInteractive)
{
<button @onclick="TriggerNotFound">Trigger Not Found</button>
}
@code {
private void TriggerNotFound()
{
Navigation.NotFound();
}
}
Событие OnNotFound можно использовать для уведомлений при вызове NavigationManager.NotFound. Событие запускается только когда вызывается NavigationManager.NotFound, а не для любого ответа с кодом 404. Например, установка HttpContextAccessor.HttpContext.Response.StatusCode в 404 не вызывает NavigationManager.NotFound/OnNotFound.
Приложения, реализующие пользовательский маршрутизатор, также могут использовать NavigationManager.NotFound. Пользовательский маршрутизатор может выводить содержимое «Не найдено» из двух источников в зависимости от состояния ответа.
Независимо от состояния ответа, путь повторного перехода к странице может быть использован, передавая его в UseStatusCodePagesWithReExecute.
app.UseStatusCodePagesWithReExecute( "/not-found", createScopeForStatusCodePages: true);Когда ответ начался, NotFoundEventArgs.Path можно воспользоваться, подписавшись на
OnNotFoundEventв маршрутизаторе.@code { [CascadingParameter] public HttpContext? HttpContext { get; set; } private void OnNotFoundEvent(object sender, NotFoundEventArgs e) { // Only execute the logic if HTTP response has started, // because setting NotFoundEventArgs.Path blocks re-execution if (HttpContext?.Response.HasStarted == false) { return; } var type = typeof(CustomNotFoundPage); var routeAttributes = type.GetCustomAttributes<RouteAttribute>(inherit: true); if (routeAttributes.Length == 0) { throw new InvalidOperationException($"The type {type.FullName} " + $"doesn't have a {nameof(RouteAttribute)} applied."); } var routeAttribute = (RouteAttribute)routeAttributes[0]; if (routeAttribute.Template != null) { e.Path = routeAttribute.Template; } } }
В следующем примере для компонентов, использующих интерактивную отрисовку на стороне сервера (интерактивная служба SSR), настраиваемое содержимое отображается в зависимости от того, где OnNotFound вызывается вызов. Если событие активируется следующим Movie компонентом, если фильм не найден при инициализации компонента, настраиваемое сообщение указывает, что запрошенный фильм не найден. Если событие активируется компонентом User в следующем примере, то другое сообщение указывает, что пользователь не найден.
Следующая NotFoundContext служба управляет контекстом и сообщением, если содержимое не найдено компонентами.
NotFoundContext.cs:
public class NotFoundContext
{
public string? Heading { get; private set; }
public string? Message { get; private set; }
public void UpdateContext(string heading, string message)
{
Heading = heading;
Message = message;
}
}
Служба регистрируется в серверном Program файле:
builder.Services.AddScoped<NotFoundContext>();
Страница NotFound внедряет NotFoundContext и отображает заголовок и сообщение.
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
@inject NotFoundContext NotFoundContext
<h3>@NotFoundContext.Heading</h3>
<div>
<p>@NotFoundContext.Message</p>
</div>
Компонент Routes с помощью параметра NotFoundPage задает компонент NotFound как страницу Not Found.
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
...
</Router>
В следующем примере показаны компоненты:
- Служба
NotFoundContextвнедряется вместе с NavigationManager. - В OnInitializedAsync,
HandleNotFoundявляется обработчиком, назначенным для событияOnNotFound.HandleNotFoundвызываетNotFoundContext.UpdateContextдля задания заголовка и сообщения для содержимого "Не найдено" в компонентеNotFound. - Компоненты обычно используют идентификатор из параметра маршрута для получения фильма или пользователя из хранилища данных, например базы данных. В следующих примерах объект не возвращается (
null) для имитации того, что происходит, когда сущность не найдена. - Если сущность не возвращается в OnInitializedAsync,
NavigationManager.NotFoundвызывается, который, в свою очередь, активирует событиеOnNotFoundи обработчик событийHandleNotFound. Не найденное содержимое отображается маршрутизатором. - Метод
HandleNotFoundотсоединяется при освобождении компонентов в IDisposable.Dispose.
Компонент Movie (Movie.razor):
@page "/movie/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext
<div>
No matter what ID is used, no matching movie is returned
from the call to GetMovie().
</div>
@code {
[Parameter]
public int Id { get; set; }
protected override async Task OnInitializedAsync()
{
NavigationManager.OnNotFound += HandleNotFound;
var movie = await GetMovie(Id);
if (movie == null)
{
NavigationManager.NotFound();
}
}
private void HandleNotFound(object? sender, NotFoundEventArgs e)
{
NotFoundContext.UpdateContext("Movie Not Found",
"Sorry! The requested movie wasn't found.");
}
private async Task<MovieItem[]?> GetMovie(int id)
{
// Simulate no movie with matching id found
return await Task.FromResult<MovieItem[]?>(null);
}
void IDisposable.Dispose()
{
NavigationManager.OnNotFound -= HandleNotFound;
}
public class MovieItem
{
public int Id { get; set; }
public string? Title { get; set; }
}
}
Компонент User (User.razor):
@page "/user/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext
<div>
No matter what ID is used, no matching user is returned
from the call to GetUser().
</div>
@code {
[Parameter]
public int Id { get; set; }
protected override async Task OnInitializedAsync()
{
NavigationManager.OnNotFound += HandleNotFound;
var user = await GetUser(Id);
if (user == null)
{
NavigationManager.NotFound();
}
}
private void HandleNotFound(object? sender, NotFoundEventArgs e)
{
NotFoundContext.UpdateContext("User Not Found",
"Sorry! The requested user wasn't found.");
}
private async Task<UserItem[]?> GetUser(int id)
{
// Simulate no user with matching id found
return await Task.FromResult<UserItem[]?>(null);
}
void IDisposable.Dispose()
{
NavigationManager.OnNotFound -= HandleNotFound;
}
public class UserItem
{
public int Id { get; set; }
public string? Name { get; set; }
}
}
Чтобы обратиться к предыдущим компонентам в локальной демонстрации с помощью тестового приложения, создайте записи в компоненте NavMenu (NavMenu.razor), чтобы получить доступ к компонентам Movie и User. Идентификаторы сущностей, передаваемые в качестве параметров маршрута, в следующем примере являются фиктивными значениями, которые не оказывают эффекта, так как они фактически не используются компонентами, имитирующими отсутствие фильма или пользователя.
В NavMenu.razor:
<div class="nav-item px-3">
<NavLink class="nav-link" href="movie/1">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Movie
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="user/2">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User
</NavLink>
</div>
Улучшенная навигация и обработка форм
Этот раздел относится к Blazor Web Apps.
Blazor Web Apps поддерживает два типа маршрутизации для запросов навигации по страницам и обработки форм:
- Обычная навигация (перекрестная навигация по документу): для URL-адреса запроса активируется полная перезагрузка.
- Улучшенная навигация (навигирование по тому же документу): Blazor перехватывает и выполняет
fetchзапрос вместо этого. Blazor затем вставляет содержимое ответа в DOM страницы. BlazorУлучшенная навигация и обработка форм избегают необходимости полностраничной перезагрузки и, при этом, сохраняют больше состояния страницы, что помогает страницам загружаться быстрее, обычно без потери позиции прокрутки пользователя на странице.
Улучшенная навигация доступна при следующих случаях:
- Скрипт Blazor Web App (
blazor.web.js) используется, а не Blazor Server скрипт (blazor.server.js) или Blazor WebAssembly скрипт (blazor.webassembly.js). - Эта функция не отключена явным образом.
- URL-адрес назначения находится в пределах внутреннего базового пространства URI (базовый путь приложения), а ссылка на страницу не имеет атрибута
data-enhance-navfalse.
Если включена маршрутизация на стороне сервера и расширенная навигация, обработчики изменения расположения вызываются только для программной навигации, инициированной из интерактивной среды выполнения. В будущих выпусках дополнительные типы навигации, такие как переход по ссылке, также могут вызывать обработчики изменения местоположения.
Когда происходит расширенная навигация, обработчики событий, LocationChanged зарегистрированные в интерактивном сервере и среде выполнения WebAssembly, обычно вызываются. В некоторых случаях обработчики изменения местоположения не могут перехватывать расширенную навигацию. Например, пользователь может переключиться на другую страницу перед тем, как интерактивная среда выполнения станет доступной. Поэтому важно, чтобы логика приложения не зависела от вызова обработчика изменения расположения, так как не гарантируется выполнение обработчика.
При вызове NavigateTo:
- Если
forceLoad— этоfalse, как и установлено по умолчанию:- Также доступна расширенная навигация по текущему URL-адресу, и расширенная навигация Blazor активирована.
- Blazor В противном случае выполняется полная перезагрузка страницы для запрошенного URL-адреса.
- Если
forceLoadэтоtrue: Blazor выполняет полную перезагрузку страницы для запрошенного URL-адреса, независимо от того, доступна ли расширенная навигация.
Вы можете обновить текущую страницу, вызвав NavigationManager.Refresh(bool forceLoad = false)функцию, которая всегда выполняет расширенную навигацию, если она доступна. Если расширенная навигация недоступна, Blazor выполняет полную перезагрузку страницы.
Navigation.Refresh();
Передайте true параметру forceLoad, чтобы убедиться, что полная перезагрузка страницы всегда выполняется, даже если имеется расширенная навигация.
Navigation.Refresh(true);
Расширенная навигация включена по умолчанию, но она может управляться иерархически и на основе каждой ссылки с помощью атрибута data-enhance-nav HTML.
В следующих примерах отключена расширенная навигация:
<a href="redirect" data-enhance-nav="false">
GET without enhanced navigation
</a>
<ul data-enhance-nav="false">
<li>
<a href="redirect">GET without enhanced navigation</a>
</li>
<li>
<a href="redirect-2">GET without enhanced navigation</a>
</li>
</ul>
Если назначение не является конечнойBlazor точкой, расширенная навигация не применяется, и JavaScript на стороне клиента повторно загружает страницу целиком. Это гарантирует отсутствие путаницы для фреймворка относительно внешних страниц, которые не должны быть внедрены в существующую страницу.
Чтобы включить расширенную обработку форм, добавьте Enhance параметр в EditForm формы или data-enhance атрибут в HTML-формы (<form>):
<EditForm ... Enhance ...>
...
</EditForm>
<form ... data-enhance ...>
...
</form>
Улучшенная обработка форм не является иерархической и не будет передаваться в дочерние формы:
Неподдерживается: нельзя задать расширенную навигацию на элементе-предке формы, чтобы включить ее для формы.
<div ... data-enhance ...>
<form ...>
<!-- NOT enhanced -->
</form>
</div>
Расширенные записи форм работают только с Blazor конечными точками. Публикация расширенной формы в непредназначенную Blazor точку приводит к ошибке.
Чтобы отключить расширенную навигацию, выполните приведенные действия.
- Удалите параметр EditForm из элемента формы (или задайте для него значение Enhance:
false). - Для HTML
<form>удалитеdata-enhanceатрибут из элемента формы (или задайте для негоfalseзначение :data-enhance="false").
BlazorУлучшенная навигация и обработка форм могут отменить динамические изменения в DOM, если обновленное содержимое не является частью рендеринга сервера. Чтобы сохранить содержимое элемента, используйте data-permanent атрибут.
В следующем примере содержимое <div> элемента динамически обновляется скриптом при загрузке страницы:
<div data-permanent>
...
</div>
После запуска Blazor на клиенте можно использовать событие enhancedload для отслеживания расширенных обновлений страниц. Это позволяет повторно применять изменения к DOM, которые, возможно, были отменены расширенным обновлением страницы.
Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));
Сведения об отключении расширенной навигации и глобальной обработки форм см. в разделе ASP.NET Core Blazor startup.
Улучшенная навигация с стати́ческой серверной отрисо́вкой (SSR) требует особого внимания при загрузке JavaScript. Дополнительные сведения см. в разделе ASP.NET Core Blazor JavaScript со статическим отображением на стороне сервера (статический SSR).
Создайте URI относительно префикса базового URI
Исходя из базового URI приложения, ToBaseRelativePath преобразует абсолютный URI в URI, относительно префикса базового URI.
Рассмотрим следующий пример:
try
{
baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
...
}
Если базовый универсальный код ресурса (URI) приложения равен https://localhost:8000, то получаются следующие результаты:
-
https://localhost:8000/segmentвinputURIприводит кbaseRelativePathвsegment. -
https://localhost:8000/segment1/segment2вinputURIприводит кbaseRelativePathвsegment1/segment2.
Если базовый URI приложения не соответствует базовому URI inputURI, будет выброшено исключение ArgumentException.
Передача https://localhost:8001/segment в inputURI приводит к следующему исключению:
System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'
Состояние журнала навигации
NavigationManager использует History API браузера, чтобы поддерживать состояние истории навигации, связанное с каждым изменением местоположения, внесенным приложением. Поддержание состояния истории особенно полезно в сценариях внешнего перенаправления, например, при аутентификации пользователей с внешними поставщиками идентификационных данных. Дополнительные сведения см. в разделе Параметры навигации.
Параметры навигации
Передайте NavigationOptions в NavigateTo для управления следующими функциями:
-
ForceLoad: Обойти маршрутизацию на стороне клиента и принудительно загрузить новую страницу с сервера, независимо от того, обрабатывается ли URI маршрутизатором на стороне клиента. Значение по умолчанию —
false. -
ReplaceHistoryEntry: замените текущую запись в стеке истории. Если
false, добавьте новую запись в стек истории. Значение по умолчанию —false. - HistoryEntryState: возвращает или задает состояние, которое будет добавлено к записи журнала.
Navigation.NavigateTo("/path", new NavigationOptions
{
HistoryEntryState = "Navigation state"
});
Дополнительные сведения о получении состояния, связанного с записью в целевой истории при управлении изменениями местоположения, см. раздел Управление и предотвращение изменений местоположения.
Строки запросов
[SupplyParameterFromQuery] Используйте атрибут, чтобы указать, что параметр компонента поступает из строки запроса.
Используйте атрибут [SupplyParameterFromQuery] с атрибутом [Parameter], чтобы указать, что параметр компонента маршрутизируемого поступает из строки запроса.
Замечание
Параметры компонента могут принимать значения параметров запроса только в маршрутизируемых компонентах с директивой @page.
Только маршрутизируемые компоненты напрямую получают параметры запроса, чтобы избежать переключения потока сведений сверху вниз и очистить порядок обработки параметров, как платформы, так и приложения. Эта конструкция позволяет избежать тонких ошибок в коде приложения, написанном при условии определенного порядка обработки параметров. Вы можете задать настраиваемые каскадные параметры или напрямую назначить их обычным параметрам компонента, чтобы передать значения параметров запроса в нераутируемые компоненты.
Параметры компонента, предоставляемые из строки запроса, поддерживают следующие типы:
-
bool,DateTime,decimaldoublefloatGuidintlongstring. - Варианты предыдущих типов, допускающие значение NULL.
- Массивы предыдущих типов, допускающие или не допускающие значение NULL.
Корректное инвариантное форматирование относительно культуры применяется для данного типа (CultureInfo.InvariantCulture).
Укажите свойство [SupplyParameterFromQuery] атрибута Name, чтобы использовать имя параметра запроса, отличное от имени параметра компонента. В следующем примере в C# именем параметра компонента является {COMPONENT PARAMETER NAME}. Для заполнителя {QUERY PARAMETER NAME} указано другое имя параметра запроса:
В отличие от свойств параметров компонента ([Parameter]), свойства [SupplyParameterFromQuery] можно пометить private, так же, как и public.
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }
Как и свойства параметра компонента ([Parameter]), [SupplyParameterFromQuery] свойства в .NET 6/7 всегда являются public свойствами. В .NET 8 и более поздних версиях свойства [SupplyParameterFromQuery] можно пометить как public или private.
[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }
В следующем примере с URL-адресом /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman:
- Свойство
Filterразрешается в значениеscifi stars. - Свойство
Pageразрешается в значение3. - Массив
Starsзаполняется из параметров запроса с именемstar(Name = "star") и преобразуется вLeVar BurtonиGary Oldman.
Замечание
Параметры строки запроса в следующем маршрутизируемом компоненте страницы также работают в немаршрутизируемом компоненте без @page директивы (например, для общего Search.razor компонента, Search используемого в других компонентах).
Search.razor:
@page "/search"
<h1>Search Example</h1>
<p>Filter: @Filter</p>
<p>Page: @Page</p>
@if (Stars is not null)
{
<p>Stars:</p>
<ul>
@foreach (var name in Stars)
{
<li>@name</li>
}
</ul>
}
@code {
[SupplyParameterFromQuery]
private string? Filter { get; set; }
[SupplyParameterFromQuery]
private int? Page { get; set; }
[SupplyParameterFromQuery(Name = "star")]
private string[]? Stars { get; set; }
}
Search.razor:
@page "/search"
<h1>Search Example</h1>
<p>Filter: @Filter</p>
<p>Page: @Page</p>
@if (Stars is not null)
{
<p>Stars:</p>
<ul>
@foreach (var name in Stars)
{
<li>@name</li>
}
</ul>
}
@code {
[Parameter]
[SupplyParameterFromQuery]
public string? Filter { get; set; }
[Parameter]
[SupplyParameterFromQuery]
public int? Page { get; set; }
[Parameter]
[SupplyParameterFromQuery(Name = "star")]
public string[]? Stars { get; set; }
}
Используйте GetUriWithQueryParameter для добавления, изменения или удаления одного или нескольких параметров запроса для текущего URL-адреса:
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})
В предыдущем примере:
- Заполнитель
{NAME}указывает имя параметра запроса. Заполнитель{VALUE}указывает значение в качестве поддерживаемого типа. Поддерживаемые типы перечислены далее в этом разделе. - Строка возвращается, равная текущему URL-адресу с одним параметром:
- Добавляется, если имя параметра запроса не существует в текущем URL-адресе.
- Изменено на значение, указываемое в том случае, если параметр запроса существует в текущем URL-адресе.
- Удаляется, если тип предоставленного значения является нулевой, а значение равно c0.
- Корректное инвариантное форматирование относительно культуры применяется для данного типа (CultureInfo.InvariantCulture).
- Имя и значение параметра запроса кодируются в виде URL-адреса.
- Все значения с соответствующим именем параметра запроса заменяются при наличии нескольких экземпляров типа.
Вызовите GetUriWithQueryParameters для создания URI, созданного из Uri, с добавлением, обновлением или удалением нескольких параметров. Для каждого значения платформа использует value?.GetType() для определения времени выполнения запроса и выбирает правильный инвариантный формат для культуры. Платформа выдает ошибку для неподдерживаемых типов.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters({PARAMETERS})
Заполнитель {PARAMETERS} — это IReadOnlyDictionary<string, object>.
Передайте строку URI в GetUriWithQueryParameters, чтобы создать новый URI из предоставленного URI с несколькими добавленными, обновленными или удаленными параметрами. Для каждого значения платформа использует value?.GetType() для определения времени выполнения запроса и выбирает правильный инвариантный формат для культуры. Платформа выдает ошибку для неподдерживаемых типов. Поддерживаемые типы перечислены далее в этом разделе.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
- Заполнитель
{URI}— это URI с параметрами запроса или без них. - Заполнитель
{PARAMETERS}— этоIReadOnlyDictionary<string, object>.
Поддерживаемые типы идентичны поддерживаемым типам для ограничений маршрута:
boolDateOnlyDateTimedecimaldoublefloatGuidintlongstringTimeOnly
К поддерживаемым типам относятся:
- Варианты предыдущих типов, допускающие значение NULL.
- Массивы предыдущих типов, допускающие или не допускающие значение NULL.
Предупреждение
С помощью сжатия, который включен по умолчанию, избегайте создания безопасных (прошедших проверку подлинности или авторизованных) интерактивных компонентов на стороне сервера, отрисовывающих данные из ненадежных источников. Ненадежные источники включают параметры маршрута, строки запроса, данные из обмена JS и любой другой источник данных, которые сторонний пользователь может контролировать (базы данных, внешние сервисы). Для получения дополнительной информации смотрите руководство по ASP.NET CoreBlazorSignalR и руководство по уменьшению угроз при интерактивной серверной обработке на стороне ASP.NET CoreBlazor.
Замена значения параметра запроса, если параметр существует
Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
| Текущий URL-адрес | Созданный URL-адрес |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&age=42 |
scheme://host/?full%20name=Morena%20Baccarin&age=42 |
scheme://host/?fUlL%20nAmE=David%20Krumholtz&AgE=42 |
scheme://host/?full%20name=Morena%20Baccarin&AgE=42 |
scheme://host/?full%20name=Jewel%20Staite&age=42&full%20name=Summer%20Glau |
scheme://host/?full%20name=Morena%20Baccarin&age=42&full%20name=Morena%20Baccarin |
scheme://host/?full%20name=&age=42 |
scheme://host/?full%20name=Morena%20Baccarin&age=42 |
scheme://host/?full%20name= |
scheme://host/?full%20name=Morena%20Baccarin |
Добавление параметра запроса и значения, если параметр не существует
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
| Текущий URL-адрес | Созданный URL-адрес |
|---|---|
scheme://host/?age=42 |
scheme://host/?age=42&name=Morena%20Baccarin |
scheme://host/ |
scheme://host/?name=Morena%20Baccarin |
scheme://host/? |
scheme://host/?name=Morena%20Baccarin |
Удаление параметра запроса, если значение параметра — null
Navigation.GetUriWithQueryParameter("full name", (string)null)
| Текущий URL-адрес | Созданный URL-адрес |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&age=42 |
scheme://host/?age=42 |
scheme://host/?full%20name=Sally%20Smith&age=42&full%20name=Summer%20Glau |
scheme://host/?age=42 |
scheme://host/?full%20name=Sally%20Smith&age=42&FuLl%20NaMe=Summer%20Glau |
scheme://host/?age=42 |
scheme://host/?full%20name=&age=42 |
scheme://host/?age=42 |
scheme://host/?full%20name= |
scheme://host/ |
Добавление, обновление и удаление параметров запроса
В следующем примере :
-
nameудаляется при наличии. -
ageдобавляется со значением25(int), если отсутствует. При наличииageобновляется и получает значение25. -
eye colorдобавляется или обновляется до значенияgreen.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["name"] = null,
["age"] = (int?)25,
["eye color"] = "green"
})
| Текущий URL-адрес | Созданный URL-адрес |
|---|---|
scheme://host/?name=David%20Krumholtz&age=42 |
scheme://host/?age=25&eye%20color=green |
scheme://host/?NaMe=David%20Krumholtz&AgE=42 |
scheme://host/?age=25&eye%20color=green |
scheme://host/?name=David%20Krumholtz&age=42&keepme=true |
scheme://host/?age=25&keepme=true&eye%20color=green |
scheme://host/?age=42&eye%20color=87 |
scheme://host/?age=25&eye%20color=green |
scheme://host/? |
scheme://host/?age=25&eye%20color=green |
scheme://host/ |
scheme://host/?age=25&eye%20color=green |
Поддержка перечислимых значений
В следующем примере :
-
full nameдобавляется или обновляется доMorena Baccarin, одного значения. - Параметры
pingдобавляются или заменяются параметрами35,16,87и240.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["full name"] = "Morena Baccarin",
["ping"] = new int?[] { 35, 16, null, 87, 240 }
})
| Текущий URL-адрес | Созданный URL-адрес |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&ping=8&ping=300 |
scheme://host/?full%20name=Morena%20Baccarin&ping=35&ping=16&ping=87&ping=240 |
scheme://host/?ping=8&full%20name=David%20Krumholtz&ping=300 |
scheme://host/?ping=35&full%20name=Morena%20Baccarin&ping=16&ping=87&ping=240 |
scheme://host/?ping=8&ping=300&ping=50&ping=68&ping=42 |
scheme://host/?ping=35&ping=16&ping=87&ping=240&full%20name=Morena%20Baccarin |
Переход с помощью добавленной или измененной строки запроса
Для перехода с помощью добавленной или измененной строки запроса передайте созданный URL-адрес в NavigateTo.
В следующем примере производится вызов:
-
GetUriWithQueryParameter для добавления или замены параметра запроса
nameс помощью значенияMorena Baccarin. - Вызывает NavigateTo, чтобы активировать навигацию по новому URL-адресу.
Navigation.NavigateTo(
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));
Строка запроса получается из свойства NavigationManager.Uri.
@inject NavigationManager Navigation
...
var query = new Uri(Navigation.Uri).Query;
Для анализа параметров строки запроса можно воспользоваться URLSearchParams в сочетании со взаимодействием JavaScript (JS):
export createQueryString = (string queryString) => new URLSearchParams(queryString);
Дополнительные сведения об изоляции JavaScript с модулями JavaScript см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.
Перейдите к именованным элементам
Перейдите к именованному элементу с использованием следующих подходов с хэш-ссылкой на элемент #. Маршруты к элементам в компоненте и маршруты к элементам во внешних компонентах используют корневой относительный путь. Начальная косая черта (/) является необязательной.
Примеры для каждого подхода демонстрируют навигацию к элементу с id и targetElement в компоненте Counter.
Якорный элемент (
<a>) сhref:<a href="/counter#targetElement">NavLink компонент с параметром
href:<NavLink href="/counter#targetElement">NavigationManager.NavigateTo передача относительного URL-адреса:
Navigation.NavigateTo("/counter#targetElement");
В следующем примере показан переход к именованным заголовкам H2 внутри компонента и к внешним компонентам.
В компонентах Home (Home.razor) и Counter (Counter.razor) поместите следующую разметку в нижней части существующей разметки компонента, чтобы использовать их в качестве целей навигации.
<div> создает искусственное вертикальное пространство для демонстрации поведения прокрутки браузера.
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
Добавьте следующий FragmentRouting компонент в приложение.
FragmentRouting.razor:
@page "/fragment-routing"
@inject NavigationManager Navigation
<PageTitle>Fragment routing</PageTitle>
<h1>Fragment routing to named elements</h1>
<ul>
<li>
<a href="/fragment-routing#targetElement">
Anchor in this component
</a>
</li>
<li>
<a href="/#targetElement">
Anchor to the <code>Home</code> component
</a>
</li>
<li>
<a href="/counter#targetElement">
Anchor to the <code>Counter</code> component
</a>
</li>
<li>
<NavLink href="/fragment-routing#targetElement">
Use a `NavLink` component in this component
</NavLink>
</li>
<li>
<button @onclick="NavigateToElement">
Navigate with <code>NavigationManager</code> to the
<code>Counter</code> component
</button>
</li>
</ul>
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
@code {
private void NavigateToElement()
{
Navigation.NavigateTo("/counter#targetElement");
}
}
Управление и предотвращение изменений местоположения
RegisterLocationChangingHandler: регистрирует обработчик для обработки входящих событий навигации. Контекст обработчика, предоставляемый LocationChangingContext, включает следующие свойства:
- TargetLocation: возвращает целевое местоположение.
- HistoryEntryState: возвращает состояние, связанное с записью в целевой истории.
- IsNavigationIntercepted: возвращает значение, указывающее, была ли навигация перехвачена из ссылки.
- CancellationToken: возвращает значение CancellationToken, определяющее, была ли отменена навигация, например, чтобы определить, активировал ли пользователь другую навигацию.
- PreventNavigation: вызывается, чтобы предотвратить продолжение навигации.
Компонент может зарегистрировать несколько обработчиков изменения местоположения в методе жизненного цикла
- При нажатии на внутренние ссылки, которые указывают на URL-адреса в базовом пути приложения.
- При навигации с помощью кнопок "Вперед" и "Назад" в браузере.
Обработчики исполняются исключительно для навигации внутри приложения. Если пользователь нажимает на ссылку, которая ведет на другой сайт, или вручную вводит в адресную строку адрес другого сайта, обработчики изменения расположения не выполняются.
Реализуйте IDisposable и удалите зарегистрированные обработчики, чтобы отменить их регистрацию. Дополнительные сведения см. в разделе ASP.NET Core Razor утилизации компонентов.
Это важно
Не пытайтесь выполнять задачи очистки DOM с помощью взаимодействия JavaScript (JS) при обработке изменений местоположения.
MutationObserver Используйте шаблон в JS клиенте. Дополнительные сведения см. в разделе Интероперабельность JavaScript в ASP.NET Core Blazor (JS interop).
В следующем примере обработчик изменения расположения регистрируется для событий навигации.
NavHandler.razor:
@page "/nav-handler"
@implements IDisposable
@inject NavigationManager Navigation
<p>
<button @onclick="@(() => Navigation.NavigateTo("/"))">
Home (Allowed)
</button>
<button @onclick="@(() => Navigation.NavigateTo("/counter"))">
Counter (Prevented)
</button>
</p>
@code {
private IDisposable? registration;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
registration =
Navigation.RegisterLocationChangingHandler(OnLocationChanging);
}
}
private ValueTask OnLocationChanging(LocationChangingContext context)
{
if (context.TargetLocation == "/counter")
{
context.PreventNavigation();
}
return ValueTask.CompletedTask;
}
public void Dispose() => registration?.Dispose();
}
Поскольку внутренняя навигация может быть отменена асинхронно, могут произойти несколько перекрывающихся вызовов зарегистрированных обработчиков. Например, несколько вызовов обработчика могут возникать, когда пользователь быстро нажимает кнопку "Назад" на странице или когда пользователь выбирает несколько ссылок перед выполнением навигации. Ниже приведена сводка по логике асинхронной навигации:
- Если регистрируются какие-либо обработчики изменения местоположения, вся навигация изначально отменяется, а затем воспроизводится, если навигация не отменена.
- Если выполняются перекрывающиеся запросы навигации, последний запрос всегда отменяет предыдущие запросы, что означает следующее:
- Приложение может рассматривать несколько нажатий кнопки "Назад" и "Вперед" как одно.
- Если пользователь выбирает несколько ссылок до завершения процесса навигации, последняя выбранная ссылка определяет навигацию.
Дополнительные сведения о передаче NavigationOptions в NavigateTo для управления записями и состоянием стека журнала навигации см. в разделе Варианты навигации.
Для получения дополнительных примеров кода см. NavigationManagerComponent в BasicTestApp (справочный источник dotnet/aspnetcore).
Замечание
Ссылки в документации на исходный код .NET обычно загружают ветку репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для конкретного релиза, используйте раскрывающийся список Переключение ветвей или тегов. Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Компонент NavigationLock перехватывает события навигации до тех пор, пока он отображается, фактически "блокирует" любую заданную навигацию до тех пор, пока не будет принято решение о продолжении или отмене. Используйте NavigationLock при перехвате навигации в течение времени существования компонента.
Параметры NavigationLock:
-
ConfirmExternalNavigation задает диалоговое окно браузера, чтобы предложить пользователю подтвердить или отменить внешнюю навигацию. Значение по умолчанию —
false. Для отображения диалогового окна подтверждения требуется начальное взаимодействие пользователя со страницей перед запуском внешней навигации по URL-адресу в адресной строке браузера. Дополнительные сведения о требовании взаимодействия см. в разделе "Окно:beforeunloadсобытие". - OnBeforeInternalNavigation задает обратный вызов для событий внутренней навигации.
В следующем компоненте NavLock:
- Прежде чем переход по ссылке на сайт Microsoft будет успешным, пользователь должен его подтвердить.
https://www.microsoft.com -
PreventNavigation вызывается, чтобы предотвратить переход, если пользователь отказывается подтвердить навигацию с помощью вызова взаимодействия JavaScript (JS), который создает диалоговое окно JS
confirm.
NavLock.razor:
@page "/nav-lock"
@inject IJSRuntime JSRuntime
@inject NavigationManager Navigation
<NavigationLock ConfirmExternalNavigation="true"
OnBeforeInternalNavigation="OnBeforeInternalNavigation" />
<p>
<button @onclick="Navigate">Navigate</button>
</p>
<p>
<a href="https://www.microsoft.com">Microsoft homepage</a>
</p>
@code {
private void Navigate()
{
Navigation.NavigateTo("/");
}
private async Task OnBeforeInternalNavigation(LocationChangingContext context)
{
var isConfirmed = await JSRuntime.InvokeAsync<bool>("confirm",
"Are you sure you want to navigate to the root page?");
if (!isConfirmed)
{
context.PreventNavigation();
}
}
}
Для дополнительных примеров кода см. компонент ConfigurableNavigationLock в BasicTestApp (справочный источник dotnet/aspnetcore).
Динамически созданные NavLink компоненты с помощью отражения
NavLink Записи компонентов можно динамически создавать из компонентов приложения с помощью отражения. В следующем примере показан общий подход к дальнейшей настройке.
Для следующей демонстрации для компонентов приложения используется согласованное стандартное соглашение об именовании:
- Имена файлов маршрутизируемых компонентов используют регистр Pascal†, например
Pages/ProductDetail.razor. - Пути к файлам маршрутизируемого компонента соответствуют их URL-адресам в формате 'kebab case', с дефисами, разделяющими слова в шаблоне маршрута компонента. Например, компонент
ProductDetailс шаблоном маршрута/product-detail(@page "/product-detail") запрашивается в браузере по относительному URL-адресу/product-detail.
†Регистр Pascal (верхний горбатый регистр) — это соглашение об именовании без пробелов и знаков препинания, где все слова, включая первое, пишутся с прописной буквы.
'Kebab case — это соглашение об именовании без пробелов и препинания, которое использует строчные буквы и дефисы между словами.
В разметке компонента Razor (NavMenu) на странице по умолчанию NavMenu.razor компоненты Home добавляются из коллекции:
<div class="nav-scrollable"
onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu"
aria-hidden="true"></span> Home
</NavLink>
</div>
+ @foreach (var name in GetRoutableComponents())
+ {
+ <div class="nav-item px-3">
+ <NavLink class="nav-link"
+ href="@Regex.Replace(name, @"(\B[A-Z]|\d+)", "-$1").ToLower()">
+ @Regex.Replace(name, @"(\B[A-Z]|\d+)", " $1")
+ </NavLink>
+ </div>
+ }
</nav>
</div>
Метод GetRoutableComponents в блоке @code :
public IEnumerable<string> GetRoutableComponents() =>
Assembly.GetExecutingAssembly()
.ExportedTypes
.Where(t => t.IsSubclassOf(typeof(ComponentBase)))
.Where(c => c.GetCustomAttributes(inherit: true)
.OfType<RouteAttribute>()
.Any())
.Where(c => c.Name != "Home" && c.Name != "Error")
.OrderBy(o => o.Name)
.Select(c => c.Name);
Приведенный выше пример не содержит следующие страницы в отрисованном списке компонентов:
-
Homeстраница: Эта страница перечислена отдельно от автоматически сгенерированных ссылок, поскольку она должна находиться в верхней части списка и устанавливать параметрMatch. -
Errorстраница ошибок: страница ошибок открывается только фреймворком и не должна быть указана.
Для демонстрации предыдущего кода в примере приложения получите Blazor Web App или Blazor WebAssembly пример приложения.