Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão do .NET 10 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, consulte a Política de Suporte do .NET e do .NET Core. Para a versão atual, consulte a versão do .NET 10 deste artigo.
Este artigo explica como disparar e manipular a navegação de página em Blazor. Embora os usuários possam navegar entre páginas diferentes usando links HTML normais, Blazor aprimora a navegação dentro do aplicativo para evitar recarregamentos de página inteira e proporcionar uma experiência mais suave. Use o NavLink componente para criar links de navegação que aplicam automaticamente o estilo quando o link corresponde à página atual. Para navegação programática e gerenciamento de URI no código C#, use o NavigationManager serviço.
Este artigo explica como disparar e manipular a navegação de página em Blazor. Use o NavLink componente para criar links de navegação que aplicam automaticamente o estilo quando o link corresponde à página atual. Para navegação programática e gerenciamento de URI no código C#, use o NavigationManager serviço.
Importante
Exemplos de código ao longo deste artigo mostram métodos executados em Navigation, que é um NavigationManager injetado em classes e componentes.
Componente NavLink
Use um componente NavLink no lugar de elementos de hiperlink HTML (<a>) ao criar links de navegação. Um componente NavLink se comporta como um elemento <a>, exceto pelo fato de alternar uma classe CSS active com base na correspondência ou não de href à URL atual. A classe active ajuda um usuário a entender qual página é a página ativa entre os links de navegação exibidos. Opcionalmente, atribua um nome de classe CSS a NavLink.ActiveClass a fim de aplicar uma classe CSS personalizada ao link renderizado quando a rota atual corresponde ao href.
NavMenu No componente (NavMenu.razor) de um Blazor aplicativo criado a partir de um Blazor modelo de projeto:
<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>
No exemplo anterior, o HomeNavLinkhref="" corresponde à URL inicial e recebe apenas a classe CSS active no caminho base padrão do aplicativo (/). O segundo NavLink recebe a classe active quando o usuário visita o componente Counter em /counter.
Há duas opções de NavLinkMatch que você pode atribuir ao atributo Match do elemento <NavLink>:
-
NavLinkMatch.All: o NavLink está ativo quando corresponde à URL atual, ignorando a cadeia de caracteres e o fragmento da consulta. Para incluir a correspondência na cadeia de caracteres/fragmento de consulta, use a opção
Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContextdefinida comotrue. - NavLinkMatch.Prefix (padrão): o NavLink está ativo quando corresponde a qualquer prefixo da URL atual.
Para adotar a lógica de correspondência personalizada, crie uma subclasse de NavLink e sobrescreva seu método ShouldMatch. Retorne true do método quando quiser aplicar a classe CSS active:
public class CustomNavLink : NavLink
{
protected override bool ShouldMatch(string currentUriAbsolute)
{
// Custom matching logic
}
}
Há duas opções de NavLinkMatch que você pode atribuir ao atributo Match do elemento <NavLink>:
- NavLinkMatch.All: o NavLink está ativo quando corresponde a toda a URL atual, incluindo a cadeia de caracteres de consulta e o fragmento.
- NavLinkMatch.Prefix (padrão): o NavLink está ativo quando corresponde a qualquer prefixo da URL atual.
Atributos adicionais do componente NavLink são passados para o elemento de âncora renderizado. No exemplo a seguir, o componente NavLink inclui o atributo target:
<NavLink href="example-page" target="_blank">Example page</NavLink>
A seguinte marcação HTML é renderizada:
<a href="example-page" target="_blank">Example page</a>
Aviso
Devido à maneira como o Blazor renderiza o conteúdo filho, renderizar componentes NavLink dentro de um loop for requer uma variável de índice local se a variável de loop de incremento é usada no conteúdo do componente (filho) NavLink:
@for (int c = 1; c < 4; c++)
{
var ct = c;
<li ...>
<NavLink ...>
<span ...></span> Product #@ct
</NavLink>
</li>
}
Usar uma variável de índice nesse cenário é um requisito para qualquer componente filho que use uma variável de loop em seu conteúdo filho, não apenas o componente NavLink.
Como alternativa, use um loop foreach com Enumerable.Range:
@foreach (var c in Enumerable.Range(1, 3))
{
<li ...>
<NavLink ...>
<span ...></span> Product #@c
</NavLink>
</li>
}
Auxiliares de estado de navegação e URI
Use NavigationManager para gerenciar URIs e navegação no código C#. NavigationManager fornece o evento e os métodos mostrados na tabela a seguir.
| Membro | Description |
|---|---|
| Uri | Obtém o URI absoluto atual. |
| BaseUri | Obtém o URI de base (com uma barra no final) que pode ser acrescentado aos caminhos de URI relativos para produzir um URI absoluto. Normalmente, BaseUri corresponde ao atributo href no elemento <base> do documento (localização de conteúdo de <head>). |
| NavigateTo | Navega até o URI especificado. Se forceLoad é false:
forceLoad é true:
Para obter mais informações, consulte a seção Navegação aprimorada e tratamento de formulários. Se |
| LocationChanged | Um evento que é acionado quando o local de navegação é alterado. Para obter mais informações, confira a seção Alterações de local. |
NotFound |
Chamado para lidar com cenários em que um recurso solicitado não é encontrado. Para obter mais informações, consulte a seção Respostas Não Encontradas . |
| ToAbsoluteUri | Converte um URI relativo em um URI absoluto. |
| ToBaseRelativePath | Com base no URI base do aplicativo, converte um URI absoluto em um URI relativo ao prefixo de URI base. Para obter um exemplo, consulte a seção Produzir um URI relativo ao prefixo de URI base. |
RegisterLocationChangingHandler |
Registra um manipulador para processar eventos de navegação recebidos. A chamada de NavigateTo sempre invoca o manipulador. |
| GetUriWithQueryParameter | Retorna um URI construído atualizando NavigationManager.Uri com um único parâmetro adicionado, atualizado ou removido. Para obter mais informações, confira a seção Cadeias de caracteres de consulta. |
| Membro | Description |
|---|---|
| Uri | Obtém o URI absoluto atual. |
| BaseUri | Obtém o URI de base (com uma barra no final) que pode ser acrescentado aos caminhos de URI relativos para produzir um URI absoluto. Normalmente, BaseUri corresponde ao atributo href no elemento <base> do documento (localização de conteúdo de <head>). |
| NavigateTo | Navega até o URI especificado. Se forceLoad é false:
forceLoad é true:
Para obter mais informações, consulte a seção Navegação aprimorada e tratamento de formulários. Se |
| LocationChanged | Um evento que é acionado quando o local de navegação é alterado. Para obter mais informações, confira a seção Alterações de local. |
| ToAbsoluteUri | Converte um URI relativo em um URI absoluto. |
| ToBaseRelativePath | Com base no URI base do aplicativo, converte um URI absoluto em um URI relativo ao prefixo de URI base. Para obter um exemplo, consulte a seção Produzir um URI relativo ao prefixo de URI base. |
RegisterLocationChangingHandler |
Registra um manipulador para processar eventos de navegação recebidos. A chamada de NavigateTo sempre invoca o manipulador. |
| GetUriWithQueryParameter | Retorna um URI construído atualizando NavigationManager.Uri com um único parâmetro adicionado, atualizado ou removido. Para obter mais informações, confira a seção Cadeias de caracteres de consulta. |
| Membro | Description |
|---|---|
| Uri | Obtém o URI absoluto atual. |
| BaseUri | Obtém o URI de base (com uma barra no final) que pode ser acrescentado aos caminhos de URI relativos para produzir um URI absoluto. Normalmente, BaseUri corresponde ao atributo href no elemento <base> do documento (localização de conteúdo de <head>). |
| NavigateTo | Navega até o URI especificado. Se forceLoad é true:
replace for true, o URI atual no histórico do navegador será substituído em vez de enviar um novo URI para a pilha de histórico. |
| LocationChanged | Um evento que é acionado quando o local de navegação é alterado. Para obter mais informações, confira a seção Alterações de local. |
| ToAbsoluteUri | Converte um URI relativo em um URI absoluto. |
| ToBaseRelativePath | Com base no URI base do aplicativo, converte um URI absoluto em um URI relativo ao prefixo de URI base. Para obter um exemplo, consulte a seção Produzir um URI relativo ao prefixo de URI base. |
RegisterLocationChangingHandler |
Registra um manipulador para processar eventos de navegação recebidos. A chamada de NavigateTo sempre invoca o manipulador. |
| GetUriWithQueryParameter | Retorna um URI construído atualizando NavigationManager.Uri com um único parâmetro adicionado, atualizado ou removido. Para obter mais informações, confira a seção Cadeias de caracteres de consulta. |
| Membro | Description |
|---|---|
| Uri | Obtém o URI absoluto atual. |
| BaseUri | Obtém o URI de base (com uma barra no final) que pode ser acrescentado aos caminhos de URI relativos para produzir um URI absoluto. Normalmente, BaseUri corresponde ao atributo href no elemento <base> do documento (localização de conteúdo de <head>). |
| NavigateTo | Navega até o URI especificado. Se forceLoad é true:
replace for true, o URI atual no histórico do navegador será substituído em vez de enviar um novo URI para a pilha de histórico. |
| LocationChanged | Um evento que é acionado quando o local de navegação é alterado. Para obter mais informações, confira a seção Alterações de local. |
| ToAbsoluteUri | Converte um URI relativo em um URI absoluto. |
| ToBaseRelativePath | Com base no URI base do aplicativo, converte um URI absoluto em um URI relativo ao prefixo de URI base. Para obter um exemplo, consulte a seção Produzir um URI relativo ao prefixo de URI base. |
| GetUriWithQueryParameter | Retorna um URI construído atualizando NavigationManager.Uri com um único parâmetro adicionado, atualizado ou removido. Para obter mais informações, confira a seção Cadeias de caracteres de consulta. |
| Membro | Description |
|---|---|
| Uri | Obtém o URI absoluto atual. |
| BaseUri | Obtém o URI de base (com uma barra no final) que pode ser acrescentado aos caminhos de URI relativos para produzir um URI absoluto. Normalmente, BaseUri corresponde ao atributo href no elemento <base> do documento (localização de conteúdo de <head>). |
| NavigateTo | Navega até o URI especificado. Se forceLoad é true:
|
| LocationChanged | Um evento que é acionado quando o local de navegação é alterado. |
| ToAbsoluteUri | Converte um URI relativo em um URI absoluto. |
| ToBaseRelativePath | Com base no URI base do aplicativo, converte um URI absoluto em um URI relativo ao prefixo de URI base. Para obter um exemplo, consulte a seção Produzir um URI relativo ao prefixo de URI base. |
Alterações de localização
Para o evento LocationChanged, LocationChangedEventArgs fornece as seguintes informações sobre eventos de navegação:
- Location: o endereço do novo local.
-
IsNavigationIntercepted: se
true, Blazor interceptou a navegação do navegador. Sefalse, então foi NavigationManager.NavigateTo que causou a navegação.
O seguinte componente :
- Navega até o componente
Counterdo aplicativo (Counter.razor) quando o botão é selecionado usando NavigateTo. - Manipula o evento com alteração de local pela assinatura de NavigationManager.LocationChanged.
O método
HandleLocationChangedé desconectado quandoDisposeé chamado pela estrutura. A desconexão do método permite a coleta de lixo do componente.A implementação do registrador registra as seguintes informações quando o botão é clicado:
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;
}
Para obter mais informações sobre o descarte de componentes, consulte Descarte de componentes Razor do ASP.NET Core.
Comportamento de redirecionamento do Gerenciador de Navegação durante a renderização estática do lado do servidor (SSR estático)
Para um redirecionamento durante a renderização estática do lado do servidor (SSR estático), NavigationManager depende do lançamento de um NavigationException que é capturado pela estrutura, que converte o erro em um redirecionamento. O código que existe após a chamada NavigateTo não é chamado. Ao usar o Visual Studio, o depurador interrompe a exceção, exigindo que você desmarque a caixa de seleção de Interrupção quando esse tipo de exceção for tratado pelo usuário na interface do usuário do Visual Studio para evitar que o depurador pare para redirecionamentos futuros.
Você pode usar a <BlazorDisableThrowNavigationException> propriedade MSBuild definida true no arquivo de projeto do aplicativo para optar por não gerar mais um NavigationException. Além disso, o código após a chamada a NavigateTo ser executada quando ele não teria sido executado antes. Esse comportamento é habilitado por padrão no modelo de projeto do .NET 10 ou posterior Blazor Web App :
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
Observação
No .NET 10 ou posterior, você pode optar por não gerar uma NavigationException configuração da <BlazorDisableThrowNavigationException> propriedade true MSBuild no arquivo de projeto do aplicativo. Para aproveitar a nova propriedade e o comportamento do MSBuild, atualize o aplicativo para o .NET 10 ou posterior.
Respostas não encontradas
NavigationManager fornece um NotFound método para lidar com cenários em que um recurso solicitado não é encontrado durante a renderização estática do lado do servidor (SSR estático) ou a renderização interativa global:
SSR estático: a chamada
NavigationManager.NotFounddefine o código de status HTTP como 404.Renderização interativa: sinaliza o Blazor roteador (
Routercomponente) para renderizar o conteúdo não encontrado.A renderização de streaming: se a navegação aprimorada estiver ativa, a renderização de streaming renderizará o conteúdo Não Encontrado sem recarregar a página. Quando a navegação aprimorada é bloqueada, a estrutura redireciona para o conteúdo Não Encontrado com uma atualização de página.
Observação
A discussão a seguir menciona que um componente Não Encontrado Razor pode ser atribuído ao parâmetro Router do componente NotFoundPage. O parâmetro funciona em conjunto com NavigationManager.NotFound e é descrito em mais detalhes mais adiante nesta seção.
A renderização de streaming só pode renderizar componentes que têm uma rota, como uma NotFoundPage atribuição (NotFoundPage="...") ou uma atribuição de páginas de middleware de reexecução de código de status (UseStatusCodePagesWithReExecute).
DefaultNotFound O conteúdo 404 ("Not found" texto sem formatação) não tem uma rota, portanto, ele não pode ser usado durante a renderização de streaming.
Observação
O fragmento de renderização Não Encontrado (<NotFound>...</NotFound>) não tem suporte no .NET 10 ou posterior.
NavigationManager.NotFound A renderização de conteúdo usa o seguinte, independentemente de a resposta ter sido iniciada ou não (em ordem):
- Se NotFoundEventArgs.Path estiver definido, renderize o conteúdo da página atribuída.
- Se
Router.NotFoundPageestiver definido, renderize a página atribuída. - Uma página de middleware para reexecução de código de status, caso seja configurada.
- Nenhuma ação se nenhuma das abordagens anteriores for adotada.
O Middleware de Reexecução de Páginas de Código de Status com UseStatusCodePagesWithReExecute tem prioridade no tratamento de problemas de roteamento de endereços baseados no navegador, como uma URL incorreta digitada na barra de endereços ou a seleção de um link sem ponto de extremidade no aplicativo.
Quando um componente é renderizado estaticamente (SSR estático) e NavigationManager.NotFound é chamado, o código de status 404 é definido na resposta:
@page "/render-not-found-ssr"
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NotFound();
}
}
Para fornecer conteúdo Não Encontrado para renderização interativa global, utilize uma página Não Encontrado (componente Razor).
Observação
O Blazor modelo de projeto inclui uma NotFound.razor página. Essa página é renderizada automaticamente sempre que NavigationManager.NotFound é chamada, possibilitando lidar com rotas ausentes com uma experiência de usuário consistente.
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>
O NotFound componente é atribuído ao parâmetro do NotFoundPage roteador.
NotFoundPage é compatível com o roteamento que pode ser utilizado em middleware de reexecução de páginas de códigos de status, inclusive middleware que não seja Blazor.
No exemplo a seguir, o componente anterior NotFound está presente na pasta do Pages aplicativo e passado para o NotFoundPage parâmetro:
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
</Router>
Quando um componente é renderizado com um modo de renderização interativo global, chamar NavigationManager.NotFound sinaliza o Blazor roteador para renderizar o NotFound componente:
@page "/render-not-found-interactive"
@inject NavigationManager Navigation
@if (RendererInfo.IsInteractive)
{
<button @onclick="TriggerNotFound">Trigger Not Found</button>
}
@code {
private void TriggerNotFound()
{
Navigation.NotFound();
}
}
Você pode usar o OnNotFound evento para notificações quando NavigationManager.NotFound é invocado. O evento só é acionado quando NavigationManager.NotFound é chamado, não para qualquer resposta 404. Por exemplo, configurar HttpContextAccessor.HttpContext.Response.StatusCode para 404 não dispara NavigationManager.NotFound/OnNotFound.
Aplicativos que implementam um roteador personalizado também podem usar NavigationManager.NotFound. O roteador personalizado pode renderizar o conteúdo Não Encontrado de duas fontes, dependendo do estado da resposta:
Independentemente do estado de resposta, o caminho de re-execução para a página pode ser usado passando-o para UseStatusCodePagesWithReExecute:
app.UseStatusCodePagesWithReExecute( "/not-found", createScopeForStatusCodePages: true);Quando a resposta for iniciada, ela NotFoundEventArgs.Path poderá ser usada assinando ao
OnNotFoundEventno roteador.@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; } } }
No exemplo a seguir para componentes que adotam a renderização interativa do lado do servidor (SSR interativa), o conteúdo personalizado é renderizado dependendo de onde OnNotFound é chamado. Se o evento for disparado pelo componente a seguir Movie quando um filme não for encontrado na inicialização do componente, uma mensagem personalizada indicará que o filme solicitado não foi encontrado. Se o evento for disparado pelo User componente no exemplo a seguir, uma mensagem diferente indicará que o usuário não foi encontrado.
O serviço a seguir NotFoundContext gerencia o contexto e a mensagem para quando o conteúdo não é encontrado pelos componentes.
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;
}
}
O serviço é registrado no arquivo do lado Program do servidor:
builder.Services.AddScoped<NotFoundContext>();
A página NotFound injeta o NotFoundContext e exibe o título e a mensagem.
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
@inject NotFoundContext NotFoundContext
<h3>@NotFoundContext.Heading</h3>
<div>
<p>@NotFoundContext.Message</p>
</div>
O Routes componente (Routes.razor) define o NotFound componente como a página Não Encontrada por meio do NotFoundPage parâmetro:
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
...
</Router>
Os componentes de exemplo a seguir:
- O
NotFoundContextserviço é injetado, juntamente com o NavigationManager. - In OnInitializedAsync,
HandleNotFoundé um manipulador de eventos atribuído aoOnNotFoundevento.HandleNotFoundchamaNotFoundContext.UpdateContextpara definir um título e uma mensagem para o conteúdo Não Encontrado noNotFoundcomponente. - Geralmente, os componentes utilizariam um ID de um parâmetro de rota para obter um filme ou um usuário de um armazenamento de dados, como um banco de dados. Nos exemplos a seguir, nenhuma entidade é retornada (
null) para simular o que acontece quando uma entidade não é encontrada. - Quando nenhuma entidade é retornada para OnInitializedAsync,
NavigationManager.NotFoundé chamada, o que, por sua vez, dispara o eventoOnNotFounde o manipulador de eventosHandleNotFound. O conteúdo não encontrado é exibido pelo roteador. - O método
HandleNotFoundé desconectado no descarte de componentes em IDisposable.Dispose.
Movie componente (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 componente (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; }
}
}
Para alcançar os componentes precedentes em uma demonstração local com um aplicativo de teste, crie entradas no componente NavMenu (NavMenu.razor) para alcançar os componentes Movie e User. As IDs das entidades, transmitidas como parâmetros de rota no exemplo a seguir, são valores simulados que não têm efeito, já que os componentes apenas simulam a situação de não encontrar um filme ou um usuário.
Em 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>
Navegação e tratamento de formulários aprimorados
Esta seção se aplica a Blazor Web Apps.
Blazor Web Apps são capazes de dois tipos de roteamento para solicitações de navegação de página e manipulação de formulários:
- Navegação normal (navegação entre documentos): um recarregamento de página inteira é disparado para a URL de solicitação.
- Navegação aprimorada (navegação no mesmo documento): Blazor intercepta a solicitação e, em vez disso, executa uma solicitação
fetch. Em seguida, Blazor insere o conteúdo da resposta no DOM da página. A navegação aprimorada e a manipulação de formulários de Blazor evitam a necessidade de um recarregamento de página inteira e preservam mais do estado da página, de modo que as páginas são carregadas mais rapidamente, sem perder a posição de rolagem do usuário na página.
A navegação aprimorada está disponível quando:
- O script do Blazor Web App (
blazor.web.js) é usado, não o script do Blazor Server (blazor.server.js) ou o script do Blazor WebAssembly (blazor.webassembly.js). - O recurso não está desabilitado explicitamente.
- A URL de destino está dentro do espaço interno do URI base (o caminho base do aplicativo) e o link para a página não tem o
data-enhance-navatributo definido comofalse.
Se o roteamento do lado do servidor e a navegação aprimorada estiverem habilitados, manipuladores de alteração de local serão invocados apenas para navegação programática iniciada a partir de um runtime interativo. Em versões futuras, tipos adicionais de navegação, como seguir um link, também poderão invocar manipuladores de alteração de localização.
Quando ocorre uma navegação aprimorada, os manipuladores de eventos LocationChanged registrados nos runtimes do Servidor Interativo e do WebAssembly são geralmente invocados. Existem casos em que os manipuladores de alteração de localização poderão não interceptar uma navegação aprimorada. Por exemplo, o usuário poderá alternar para outra página antes de um runtime interativo ficar disponível. Portanto, é importante que a lógica do aplicativo não dependa da invocação de um manipulador de alteração de localização, já que não há garantia de execução do manipulador.
Ao chamar NavigateTo:
- Se
forceLoadéfalse, que é o padrão:- A navegação aprimorada está disponível na URL atual, a navegação aprimorada de Blazor está ativada.
- Caso contrário, Blazor executará um recarregamento de página inteira para a URL solicitada.
- Se
forceLoadfortrue: Blazor executará um carregamento de página inteira para a URL solicitada, independentemente de a navegação aprimorada estar disponível ou não.
Você pode atualizar a página atual chamando NavigationManager.Refresh(bool forceLoad = false), que sempre executa uma navegação aprimorada, se disponível. Se a navegação aprimorada não estiver disponível, Blazor executará um recarregamento de página inteira.
Navigation.Refresh();
Passe true para o parâmetro forceLoad para garantir que um recarregamento de página inteira seja sempre executada, mesmo se a navegação aprimorada estiver disponível:
Navigation.Refresh(true);
A navegação aprimorada está habilitada por padrão, mas pode ser controlada hierarquicamente e por link utilizando o atributo HTML data-enhance-nav.
Os exemplos a seguir desabilitam a navegação aprimorada:
<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>
Se o destino for um ponto de extremidade diferente de Blazor, a navegação aprimorada não será aplicada e o JavaScript do lado do cliente se repetirá como um carregamento de toda a página. Isso garante que não haja nenhuma confusão na estrutura sobre páginas externas que não devem ser corrigidas em uma página existente.
Para habilitar o tratamento aprimorado de formulários, adicione o parâmetro Enhance aos formulários EditForm ou o atributo data-enhance aos formulários HTML (<form>):
<EditForm ... Enhance ...>
...
</EditForm>
<form ... data-enhance ...>
...
</form>
O tratamento aprimorado de formulários não é hierárquico e não flui para os formulários secundários:
Não suportado: não é possível definir a navegação aprimorada em um elemento ancestral do formulário para habilitar a navegação aprimorada para o formulário.
<div ... data-enhance ...>
<form ...>
<!-- NOT enhanced -->
</form>
</div>
As postagens do formulário aprimorado só funcionam com pontos de extremidade Blazor. A postagem de um formulário aprimorado em um ponto de extremidade diferente de Blazor resulta em um erro.
Para desabilitar a navegação aprimorada:
- Para um EditForm, remova o parâmetro Enhance do elemento do formulário (ou defina-o como
false:Enhance="false"). - Para um HTML
<form>, remova o atributodata-enhancedo elemento do formulário (ou defina-o comofalse:data-enhance="false").
A navegação aprimorada e o manuseio de formulários da Blazor podem desfazer alterações dinâmicas no DOM se o conteúdo atualizado não fizer parte da renderização do servidor. Para preservar o conteúdo de um elemento, utilize o atributo data-permanent.
No exemplo a seguir, o conteúdo do elemento <div> é atualizado dinamicamente por um script quando a página é carregada:
<div data-permanent>
...
</div>
Uma vez que Blazor tenha sido iniciado no cliente, você poderá utilizar o evento enhancedload para escutar as atualizações aprimoradas da página. Isso permite a reaplicação de alterações no DOM que podem ter sido desfeitas por uma atualização de página aprimorada.
Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));
Para desabilitar a navegação aprimorada e o tratamento de formulários globalmente, consulte ASP.NET Core Blazor inicialização.
A navegação aprimorada com renderização estática do lado do servidor (SSR estática) exige atenção especial ao carregar o JavaScript. Para obter mais informações, confira JavaScript do ASP.NET Core Blazor com renderização estática do lado do servidor (SSR estática).
Produzir um URI relativo ao prefixo de URI base
Com base no URI base do aplicativo, ToBaseRelativePath converte um URI absoluto em um URI relativo ao prefixo de URI base.
Considere o exemplo a seguir:
try
{
baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
...
}
Se o URI base do aplicativo for https://localhost:8000, os seguintes resultados serão obtidos:
- Passar
https://localhost:8000/segmenteminputURIresulta em umbaseRelativePathdesegment. - Passar
https://localhost:8000/segment1/segment2eminputURIresulta em umbaseRelativePathdesegment1/segment2.
Se o URI base do aplicativo não corresponder ao URI base de inputURI, um ArgumentException será gerado.
Passar https://localhost:8001/segment em inputURI resulta na exceção a seguir:
System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'
Estado do histórico de navegação
O NavigationManager usa a API de Histórico do navegador para manter o estado do histórico de navegação associado a cada alteração de local feita pelo aplicativo. Manter o estado do histórico é particularmente útil em cenários de redirecionamento externo, por exemplo, na autenticação de usuários com provedores de identidade externos. Para obter mais informações, confira a seção Opções de Navegação.
Opções de navegação
Transmita NavigationOptions a NavigateTo para controlar os seguintes comportamentos:
-
ForceLoad: ignora o roteamento do lado do cliente e força o navegador a carregar a nova página do servidor, independentemente de o URI ser manipulado pelo roteador do lado do cliente. O valor padrão é
false. -
ReplaceHistoryEntry: substitui a entrada atual na pilha de histórico. Se
false, acrescente a nova entrada à pilha de histórico. O valor padrão éfalse. - HistoryEntryState: obtém ou define o estado a ser acrescentado à entrada de histórico.
Navigation.NavigateTo("/path", new NavigationOptions
{
HistoryEntryState = "Navigation state"
});
Para obter mais informações sobre como obter o estado associado à entrada de histórico de destino durante o tratamento de alterações de local, confira a seção Manipular/impedir alterações de local.
Cadeias de consulta
Use o atributo [SupplyParameterFromQuery] para especificar que um parâmetro de componente é proveniente da string de consulta.
Use o atributo [SupplyParameterFromQuery] com o atributo [Parameter] para especificar que um parâmetro de componente de um componente roteável pode vir da cadeia de caracteres de consulta.
Observação
Os parâmetros de componente só podem receber valores de parâmetro de consulta em componentes roteáveis com uma diretiva @page.
Somente os componentes roteáveis recebem diretamente parâmetros de consulta para evitar subverter o fluxo de informações de cima para baixo e tornar clara a ordem de processamento de parâmetros, tanto pela estrutura quanto pelo aplicativo. Esse design evita bugs sutis no código do aplicativo que foi escrito assumindo uma ordem de processamento de parâmetro específica. Você é livre para definir parâmetros em cascata personalizados ou atribuir diretamente a parâmetros de componentes regulares para passar valores de parâmetro de consulta para componentes não roteáveis.
Os parâmetros de componente fornecidos da cadeia de caracteres de consulta dão suporte aos seguintes tipos:
-
bool,DateTime,decimal,double,floatGuidintlongstring. - Variantes anuláveis dos tipos anteriores.
- Matrizes dos tipos anteriores, sejam anuláveis, sejam não anuláveis.
A formatação sem variação de cultura correta é aplicada ao tipo determinado (CultureInfo.InvariantCulture).
Especifique a propriedade [SupplyParameterFromQuery] do atributo Name para usar um nome de parâmetro de consulta diferente do nome do parâmetro do componente. No exemplo a seguir, o nome C# do parâmetro de componente é {COMPONENT PARAMETER NAME}. Um nome de parâmetro de consulta diferente é especificado para o espaço reservado {QUERY PARAMETER NAME}:
Ao contrário das propriedades de parâmetro do componente ([Parameter]), as propriedades [SupplyParameterFromQuery] podem ser marcadas private além de public.
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }
Assim como as propriedades do parâmetro do componente ([Parameter]), as propriedades [SupplyParameterFromQuery] são sempre propriedades public no .NET 6/7. No .NET 8 ou posteriores, as propriedades [SupplyParameterFromQuery] podem ser marcadas public ou private.
[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }
No exemplo a seguir, com uma URL de /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman:
- A propriedade
Filterresolve-se parascifi stars. - A propriedade
Pageresolve-se para3. - A matriz
Starsé preenchida com base em parâmetros de consulta chamadosstar(Name = "star") e resolve paraLeVar BurtoneGary Oldman.
Observação
Os parâmetros de cadeia de caracteres de consulta no seguinte componente de página roteável também funcionam em um componente não roteável sem uma diretiva @page (por exemplo, Search.razor para um componente Search compartilhado usado em outros componentes).
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; }
}
Use GetUriWithQueryParameter para adicionar, alterar ou remover um ou mais parâmetros de consulta na URL atual:
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})
No exemplo anterior:
- O espaço reservado
{NAME}especifica o nome do parâmetro de consulta. O espaço reservado{VALUE}especifica o valor como um tipo com suporte. Os tipos com suporte são listados posteriormente nesta seção. - Uma cadeia de caracteres é retornada igual à URL atual com um único parâmetro:
- Adicionado se o nome do parâmetro de consulta não existir na URL atual.
- Atualizado para o valor fornecido se o parâmetro de consulta existir na URL atual.
- Removido se o tipo do valor fornecido for anulável e o valor for
null.
- A formatação sem variação de cultura correta é aplicada ao tipo determinado (CultureInfo.InvariantCulture).
- O nome e o valor do parâmetro de consulta são codificados em URL.
- Todos os valores com o nome do parâmetro de consulta correspondente serão substituídos se houver várias instâncias do tipo.
Chame GetUriWithQueryParameters para criar um URI construído de Uri com vários parâmetros adicionados, atualizados ou removidos. Para cada valor, a estrutura usa value?.GetType() para determinar o tipo de tempo de execução para cada parâmetro de consulta e seleciona a formatação cultura-invariante correta. O framework gera um erro para tipos não suportados.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters({PARAMETERS})
O espaço reservado {PARAMETERS} é um IReadOnlyDictionary<string, object>.
Transmita uma cadeia de caracteres de URI para GetUriWithQueryParameters a fim de gerar um novo URI de um URI fornecido com vários parâmetros adicionados, atualizados ou removidos. Para cada valor, a estrutura usa value?.GetType() para determinar o tipo de tempo de execução para cada parâmetro de consulta e seleciona a formatação cultura-invariante correta. O framework gera um erro para tipos não suportados. Os tipos com suporte são listados posteriormente nesta seção.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
- O espaço reservado
{URI}é o URI com ou sem uma cadeia de caracteres de consulta. - O espaço reservado
{PARAMETERS}é umIReadOnlyDictionary<string, object>.
Os tipos com suporte são idênticos aos tipos com suporte em restrições de rota:
boolDateOnlyDateTimedecimaldoublefloatGuidintlongstringTimeOnly
Os tipos compatíveis incluem:
- Variantes anuláveis dos tipos anteriores.
- Matrizes dos tipos anteriores, sejam anuláveis, sejam não anuláveis.
Aviso
Com a compressão, que está habilitada por padrão, evite criar componentes interativos seguros (autenticados/autorizados) do lado do servidor que renderizam dados de fontes não confiáveis. As fontes não confiáveis incluem parâmetros de rota, cadeias de caracteres de consulta, dados de interoperação com JS e qualquer outra fonte de dados que um usuário de terceiros possa controlar (bancos de dados, serviços externos). Para obter mais informações, consulte Orientações do ASP.NET Core BlazorSignalR e Orientações para mitigação de ameaças na renderização interativa do lado do servidor no ASP.NET Core Blazor.
Substitui um valor de parâmetro de consulta quando o parâmetro existe
Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
| URL atual | URL gerada |
|---|---|
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 |
Acrescenta um parâmetro de consulta e um valor quando o parâmetro não existe
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
| URL atual | URL gerada |
|---|---|
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 |
Remove um parâmetro de consulta quando o valor do parâmetro é null
Navigation.GetUriWithQueryParameter("full name", (string)null)
| URL atual | URL gerada |
|---|---|
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/ |
Adiciona, atualiza e remove parâmetros de consulta
No exemplo a seguir:
-
nameé removido, se presente. -
ageé adicionado com um valor de25(int), se não estiver presente. Se estiver presente,ageserá atualizado para um valor de25. -
eye coloré adicionado ou atualizado para um valor degreen.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["name"] = null,
["age"] = (int?)25,
["eye color"] = "green"
})
| URL atual | URL gerada |
|---|---|
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 |
Suporte a valores enumeráveis
No exemplo a seguir:
-
full nameé adicionado ou atualizado paraMorena Baccarin, um valor único. -
pingparâmetros são adicionados ou substituídos por35,16,87e240.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["full name"] = "Morena Baccarin",
["ping"] = new int?[] { 35, 16, null, 87, 240 }
})
| URL atual | URL gerada |
|---|---|
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 |
Navegar com uma cadeia de caracteres de consulta adicionada ou modificada
Para navegar com uma cadeia de caracteres de consulta adicionada ou modificada, transmita uma URL gerada a NavigateTo.
O exemplo abaixo chama:
-
GetUriWithQueryParameter para adicionar ou substituir o parâmetro de consulta
nameusando um valor deMorena Baccarin. - Chama NavigateTo a fim de disparar a navegação para a nova URL.
Navigation.NavigateTo(
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));
A cadeia de caracteres de consulta de uma solicitação é obtida da propriedade NavigationManager.Uri:
@inject NavigationManager Navigation
...
var query = new Uri(Navigation.Uri).Query;
Para analisar os parâmetros de uma cadeia de consulta, uma abordagem é usar URLSearchParams com interoperabilidade JavaScript (JS):
export createQueryString = (string queryString) => new URLSearchParams(queryString);
Para obter mais informações sobre o isolamento JavaScript com módulos JavaScript, confira Chamar funções JavaScript de métodos do .NET no ASP.NET Core Blazor.
Navegar até elementos nomeados
Navegue até um elemento nomeado usando as abordagens a seguir com uma referência de hash (#) ao elemento. As rotas para elementos dentro do componente e as rotas para elementos em componentes externos usam caminhos relativos à raiz. Uma barra à esquerda (/) é opcional.
Exemplos para cada uma das abordagens a seguir demonstram a navegação para um elemento com um id do targetElement no componente Counter:
Elemento âncora (
<a>) com umhref:<a href="/counter#targetElement">Componente NavLink com um
href:<NavLink href="/counter#targetElement">NavigationManager.NavigateTo passando a URL relativa:
Navigation.NavigateTo("/counter#targetElement");
O exemplo a seguir demonstra como navegar para títulos H2 nomeados dentro de um componente e para componentes externos.
Nos componentes Home (Home.razor) e Counter (Counter.razor), coloque a marcação a seguir na parte inferior da marcação de componente existente para servir como destinos de navegação. O <div> cria um espaço vertical artificial para demonstrar o comportamento de rolagem do navegador:
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
Adicione o componente FragmentRouting a seguir ao aplicativo.
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");
}
}
Manipular/evitar mudanças de localização
RegisterLocationChangingHandlerRegistra um manipulador para processar eventos de navegação recebidos. O contexto do manipulador fornecido pelo LocationChangingContext inclui as seguintes propriedades:
- TargetLocation: obtém o local de destino.
- HistoryEntryState: obtém o estado associado à entrada do histórico de destino.
- IsNavigationIntercepted: obtém se a navegação foi interceptada de um link ou não.
- CancellationToken: obtém um CancellationToken para determinar se a navegação foi cancelada, por exemplo, para determinar se o usuário iniciou uma navegação diferente.
- PreventNavigation: chamado para impedir que a navegação continue.
Um componente pode registrar vários manipuladores de mudança de localização no método de ciclo de vidaOnAfterRender{Async}. A navegação invoca todos os manipuladores de mudança de local registrados em todo o aplicativo, abrangendo vários componentes, e qualquer navegação interna executa todos eles em paralelo. Além de NavigateTo, os manipuladores são invocados:
- Ao selecionar links internos, que são links que apontam para URLs no caminho base do aplicativo.
- Ao navegar usando os botões para frente e para trás em um navegador.
Os manipuladores são executados apenas para navegação interna dentro do aplicativo. Se o usuário selecionar um link que navegue até um site diferente ou alterar a barra de endereços para um site diferente manualmente, os manipuladores de alteração de localização não serão executados.
Implemente IDisposable e descarte manipuladores registrados para cancelá-los. Para obter mais informações, consulte descarte de componente do ASP.NET CoreRazor.
Importante
Não tente executar tarefas de limpeza do DOM (Document Object Model) por meio da interoperabilidade JavaScript (JS) ao lidar com mudanças de localização. Use o padrão MutationObserver em JS no cliente. Para obter mais informações, confira Interoperabilidade com JavaScript no ASP.NET Core Blazor(JSinterop).
No exemplo a seguir, um manipulador para mudança de localização é registrado para eventos de navegação.
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();
}
Como a navegação interna pode ser cancelada de forma assíncrona, podem ocorrer várias chamadas sobrepostas a manipuladores registrados. Por exemplo, várias chamadas de manipulador podem ocorrer quando o usuário seleciona rapidamente o botão Voltar em uma página ou seleciona vários links antes de uma navegação ser executada. Veja abaixo um resumo da lógica de navegação assíncrona:
- Se algum manipulador de mudança de local for registrado, toda a navegação é inicialmente revertida e depois reproduzida se a navegação não for cancelada.
- Se forem feitas solicitações de navegação sobrepostas, a solicitação mais recente sempre cancelará solicitações anteriores, o que significa o seguinte:
- O aplicativo pode tratar várias seleções de botão Voltar e Avançar como uma única seleção.
- Se o usuário selecionar vários links antes da conclusão da navegação, o último link selecionado determinará a navegação.
Para obter mais informações sobre como transmitir NavigationOptions a NavigateTo para controlar as entradas e o estado da pilha de histórico de navegação, confira a seção Opções de navegação.
Para obter um código de exemplo adicional, confira o NavigationManagerComponent no BasicTestApp (fonte de referência dotnet/aspnetcore).
Observação
Os links de documentação para o código fonte de referência do .NET geralmente carregam a ramificação padrão do repositório, que representa o desenvolvimento atual para a próxima versão do .NET. Para selecionar uma marca para uma versão específica, use a lista suspensa para Alternar branches ou marcas. Para saber mais, confira Como selecionar uma marca de versão do código-fonte do ASP.NET Core (dotnet/AspNetCore.Docs #26205).
O NavigationLock componente intercepta eventos de navegação enquanto é renderizado, efetivamente "bloqueando" qualquer navegação até que seja tomada uma decisão de prosseguir ou cancelar. Use NavigationLock quando o escopo da interceptação de navegação puder ser definido como o tempo de vida de um componente.
Parâmetros de NavigationLock:
-
ConfirmExternalNavigation define um diálogo do navegador para solicitar que o usuário confirme ou cancele a navegação externa. O valor padrão é
false. A exibição do diálogo de confirmação requer a interação inicial do usuário com a página antes de disparar a navegação externa com a URL na barra de endereços do navegador. Para obter mais informações sobre o requisito de interação, consulte Janela:beforeunloadevento. - OnBeforeInternalNavigation define um retorno de chamada para eventos de navegação interna.
No seguinte componente NavLock:
- Uma tentativa de seguir o link para o site da Microsoft precisa ser confirmada pelo usuário antes que a navegação até
https://www.microsoft.comseja bem-sucedida. -
PreventNavigation é chamado para impedir que a navegação ocorra se o usuário se recusar a confirmar a navegação por meio de uma chamada de interoperabilidade JavaScript (JS) que gera o JS
confirmdiálogo.
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();
}
}
}
Para obter um código de exemplo adicional, confira o componente ConfigurableNavigationLock no BasicTestApp (fonte de referência dotnet/aspnetcore).
Componentes gerados NavLink dinamicamente por meio da reflexão
As entradas do componente NavLink podem ser criadas dinamicamente a partir dos componentes do aplicativo por meio da reflexão. O exemplo a seguir demonstra a abordagem geral para personalização adicional.
Para a demonstração a seguir, uma convenção de nomenclatura padrão consistente é usada para os componentes do aplicativo:
- Os nomes de arquivos de componentes que podem ser roteados usam o formato Pascal case†, por exemplo,
Pages/ProductDetail.razor. - Os caminhos de arquivo de componentes roteáveis correspondem às suas URLs em kebab case‡ com hifens aparecendo entre as palavras no modelo da rota de um componente. Por exemplo, um componente
ProductDetailcom um modelo de rota/product-detail(@page "/product-detail") é solicitado em um navegador na URL relativa/product-detail.
PascalCase† (camelCase iniciada por maiúscula) é uma convenção de nomenclatura sem espaços e pontuação e com a primeira letra de cada palavra maiúscula, incluindo a primeira palavra.
‡Kebab case é uma convenção de nomes sem espaços e pontuação que utiliza letras minúsculas e traços entre as palavras.
Na marcação Razor do componente NavMenu (NavMenu.razor) na página padrão Home, os componentes NavLink são adicionados de uma coleção:
<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>
O método GetRoutableComponents no bloco @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);
O exemplo anterior não inclui as seguintes páginas na lista renderizada de componentes:
- Página
Home: a página é listada separadamente dos links gerados automaticamente porque ela deve aparecer na parte superior da lista e definir o parâmetroMatch. - Página
Error: a página de erro só é acessada pelo framework e não deve ser listada.
Para uma demonstração do código anterior em um aplicativo de exemplo, obtenha o Blazor Web App ou o Blazor WebAssembly aplicativo de exemplo.