Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Annotazioni
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 10 di questo articolo.
Avvertimento
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 10 di questo articolo.
Questo articolo illustra come attivare e gestire lo spostamento tra le pagine in Blazor. Anche se gli utenti possono spostarsi tra pagine diverse usando normali collegamenti HTML, Blazor migliora la navigazione all'interno dell'applicazione per evitare ricaricamenti di pagina completi e offrire un'esperienza più fluida. Utilizzare il NavLink componente per creare collegamenti di spostamento che applicano automaticamente lo stile quando il collegamento corrisponde alla pagina corrente. Per la navigazione e gestione degli URI a livello di programmazione nel codice C#, usare il servizio NavigationManager.
Questo articolo illustra come attivare e gestire lo spostamento tra le pagine in Blazor. Utilizzare il NavLink componente per creare collegamenti di spostamento che applicano automaticamente lo stile quando il collegamento corrisponde alla pagina corrente. Per la navigazione programmata e la gestione degli URI nel codice C#, usare il servizio NavigationManager.
Importante
Gli esempi di codice in questo articolo illustrano i metodi chiamati su Navigation, che è un oggetto inserito NavigationManager in classi e componenti.
Componente NavLink
Usare un componente NavLink al posto degli elementi del collegamento ipertestuale HTML (<a>) quando si creano collegamenti di navigazione. Un NavLink componente si comporta come un <a> elemento, ad eccezione del fatto che attiva o disattiva una active classe CSS in base a se href corrisponde all'URL corrente. La active classe aiuta un utente a capire quale pagina è la pagina attiva tra i collegamenti di spostamento visualizzati. Facoltativamente, assegnare a NavLink.ActiveClass un nome di classe CSS per applicare una classe CSS personalizzata al collegamento reso quando la route corrente corrisponde a href.
Nel componente NavMenu (NavMenu.razor) di un'app Blazor creata da un modello di progetto 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>
Nell'esempio precedente, il HomeNavLinkhref="" corrisponde all'URL principale e riceve solo la classe CSS active nel percorso di base predefinito dell'app (/). Il secondo NavLink riceve la active classe quando l'utente visita il Counter componente in /counter.
Sono disponibili due NavLinkMatch opzioni che è possibile assegnare all'attributo Match dell'elemento <NavLink> :
-
NavLinkMatch.All: il NavLink è attivo quando corrisponde all'URL corrente, ignorando la stringa di query e il frammento. Per includere la corrispondenza nella stringa di query/frammento, utilizzare il
Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContextswitch impostato sutrue. - NavLinkMatch.Prefix (impostazione predefinita): l'oggetto NavLink è attivo quando corrisponde a qualsiasi prefisso dell'URL corrente.
Per adottare la logica di corrispondenza personalizzata, sottoclassare NavLink e sovrascrivere il metodo ShouldMatch. Restituire true dal metodo quando si desidera applicare la classe CSS active:
public class CustomNavLink : NavLink
{
protected override bool ShouldMatch(string currentUriAbsolute)
{
// Custom matching logic
}
}
Sono disponibili due NavLinkMatch opzioni che è possibile assegnare all'attributo Match dell'elemento <NavLink> :
- NavLinkMatch.All: il NavLink è attivo quando corrisponde all'intero URL corrente, inclusa la stringa di query e il frammento.
- NavLinkMatch.Prefix (impostazione predefinita): l'oggetto NavLink è attivo quando corrisponde a qualsiasi prefisso dell'URL corrente.
Gli attributi aggiuntivi NavLink dei componenti vengono passati al tag di ancoraggio renderizzato. Nell'esempio seguente il NavLink componente include l'attributo target :
<NavLink href="example-page" target="_blank">Example page</NavLink>
Il seguente markup HTML viene visualizzato.
<a href="example-page" target="_blank">Example page</a>
Avvertimento
A causa del modo in cui Blazor esegue il rendering del contenuto figlio, il rendering dei componenti NavLink all'interno di un ciclo for richiede una variabile di indice locale se la variabile del ciclo incrementale viene usata nel contenuto del componente figlio NavLink.
@for (int c = 1; c < 4; c++)
{
var ct = c;
<li ...>
<NavLink ...>
<span ...></span> Product #@ct
</NavLink>
</li>
}
L'uso di una variabile di indice in questo scenario è un requisito per qualsiasi componente figlio che utilizza una variabile di ciclo nel suo contenuto figlio, non solo per il componente NavLink.
In alternativa, usare un ciclo foreach con Enumerable.Range:
@foreach (var c in Enumerable.Range(1, 3))
{
<li ...>
<NavLink ...>
<span ...></span> Product #@c
</NavLink>
</li>
}
Helper di URI e dello stato di navigazione
Usare NavigationManager per gestire gli URI e lo spostamento nel codice C#. NavigationManager fornisce l'evento e i metodi illustrati nella tabella seguente.
| Membro | Description |
|---|---|
| Uri | Ottiene l'URI assoluto corrente. |
| BaseUri | Ottiene l'URI di base (con una barra finale) che può essere anteposto ai percorsi URI relativi per produrre un URI assoluto. In genere, BaseUri corrisponde all'attributo href dell'elemento del <base> documento (posizione del <head> contenuto). |
| NavigateTo | Naviga all'URI specificato. Se forceLoad è false:
forceLoad è true:
Per altre informazioni, vedere la sezione Navigazione avanzata e gestione dei moduli. Se |
| LocationChanged | Evento che viene attivato quando la posizione di navigazione è cambiata. Per altre informazioni, vedere la sezione Modifiche alla posizione . |
NotFound |
Chiamato per gestire gli scenari in cui non viene trovata una risorsa richiesta. Per altre informazioni, vedere la sezione Risposte non trovate . |
| ToAbsoluteUri | Converte un URI relativo in un URI assoluto. |
| ToBaseRelativePath | In base all'URI di base dell'app, converte un URI assoluto in un URI relativo al prefisso dell'URI di base. Per un esempio, vedere la sezione Produrre un URI relativo al prefisso dell'URI di base. |
RegisterLocationChangingHandler |
Registra un gestore per elaborare gli eventi di navigazione in arrivo. La chiamata NavigateTo richiama sempre il gestore. |
| GetUriWithQueryParameter | Restituisce un URI costruito aggiornando NavigationManager.Uri con un singolo parametro aggiunto, aggiornato o rimosso. Per ulteriori informazioni, vedere la sezione stringhe di query. |
| Membro | Description |
|---|---|
| Uri | Ottiene l'URI assoluto corrente. |
| BaseUri | Ottiene l'URI di base (con una barra finale) che può essere anteposto ai percorsi URI relativi per produrre un URI assoluto. In genere, BaseUri corrisponde all'attributo href dell'elemento del <base> documento (posizione del <head> contenuto). |
| NavigateTo | Naviga all'URI specificato. Se forceLoad è false:
forceLoad è true:
Per altre informazioni, vedere la sezione Navigazione avanzata e gestione dei moduli. Se |
| LocationChanged | Evento che viene attivato quando la posizione di navigazione è cambiata. Per altre informazioni, vedere la sezione Modifiche alla posizione . |
| ToAbsoluteUri | Converte un URI relativo in un URI assoluto. |
| ToBaseRelativePath | In base all'URI di base dell'app, converte un URI assoluto in un URI relativo al prefisso dell'URI di base. Per un esempio, vedere la sezione Produrre un URI relativo al prefisso dell'URI di base. |
RegisterLocationChangingHandler |
Registra un gestore per elaborare gli eventi di navigazione in arrivo. La chiamata NavigateTo richiama sempre il gestore. |
| GetUriWithQueryParameter | Restituisce un URI costruito aggiornando NavigationManager.Uri con un singolo parametro aggiunto, aggiornato o rimosso. Per ulteriori informazioni, vedere la sezione stringhe di query. |
| Membro | Description |
|---|---|
| Uri | Ottiene l'URI assoluto corrente. |
| BaseUri | Ottiene l'URI di base (con una barra finale) che può essere anteposto ai percorsi URI relativi per produrre un URI assoluto. In genere, BaseUri corrisponde all'attributo href dell'elemento del <base> documento (posizione del <head> contenuto). |
| NavigateTo | Naviga all'URI specificato. Se forceLoad è true:
replace è true, l'URI corrente nella cronologia del browser viene sostituito invece di eseguire il push di un nuovo URI nello stack di cronologia. |
| LocationChanged | Evento che viene attivato quando la posizione di navigazione è cambiata. Per altre informazioni, vedere la sezione Modifiche alla posizione . |
| ToAbsoluteUri | Converte un URI relativo in un URI assoluto. |
| ToBaseRelativePath | In base all'URI di base dell'app, converte un URI assoluto in un URI relativo al prefisso dell'URI di base. Per un esempio, vedere la sezione Produrre un URI relativo al prefisso dell'URI di base. |
RegisterLocationChangingHandler |
Registra un gestore per elaborare gli eventi di navigazione in arrivo. La chiamata NavigateTo richiama sempre il gestore. |
| GetUriWithQueryParameter | Restituisce un URI costruito aggiornando NavigationManager.Uri con un singolo parametro aggiunto, aggiornato o rimosso. Per ulteriori informazioni, vedere la sezione stringhe di query. |
| Membro | Description |
|---|---|
| Uri | Ottiene l'URI assoluto corrente. |
| BaseUri | Ottiene l'URI di base (con una barra finale) che può essere anteposto ai percorsi URI relativi per produrre un URI assoluto. In genere, BaseUri corrisponde all'attributo href dell'elemento del <base> documento (posizione del <head> contenuto). |
| NavigateTo | Naviga all'URI specificato. Se forceLoad è true:
replace è true, l'URI corrente nella cronologia del browser viene sostituito invece di eseguire il push di un nuovo URI nello stack di cronologia. |
| LocationChanged | Evento che viene attivato quando la posizione di navigazione è cambiata. Per altre informazioni, vedere la sezione Modifiche alla posizione . |
| ToAbsoluteUri | Converte un URI relativo in un URI assoluto. |
| ToBaseRelativePath | In base all'URI di base dell'app, converte un URI assoluto in un URI relativo al prefisso dell'URI di base. Per un esempio, vedere la sezione Produrre un URI relativo al prefisso dell'URI di base. |
| GetUriWithQueryParameter | Restituisce un URI costruito aggiornando NavigationManager.Uri con un singolo parametro aggiunto, aggiornato o rimosso. Per ulteriori informazioni, vedere la sezione stringhe di query. |
| Membro | Description |
|---|---|
| Uri | Ottiene l'URI assoluto corrente. |
| BaseUri | Ottiene l'URI di base (con una barra finale) che può essere anteposto ai percorsi URI relativi per produrre un URI assoluto. In genere, BaseUri corrisponde all'attributo href dell'elemento del <base> documento (posizione del <head> contenuto). |
| NavigateTo | Naviga all'URI specificato. Se forceLoad è true:
|
| LocationChanged | Evento che viene attivato quando la posizione di navigazione è cambiata. |
| ToAbsoluteUri | Converte un URI relativo in un URI assoluto. |
| ToBaseRelativePath | In base all'URI di base dell'app, converte un URI assoluto in un URI relativo al prefisso dell'URI di base. Per un esempio, vedere la sezione Produrre un URI relativo al prefisso dell'URI di base. |
Modifiche alla posizione
Per l'evento LocationChanged, LocationChangedEventArgs fornisce le seguenti informazioni sugli eventi di navigazione:
- Location: L'URL della nuova posizione.
-
IsNavigationIntercepted: se
true, Blazor ha intercettato la navigazione dal browser. Sefalse, NavigationManager.NavigateTo ha causato la navigazione.
Componente seguente:
- Passa al componente dell'app
Counter(Counter.razor) quando si seleziona un pulsante con NavigateTo. - Gestisce l'evento di cambiamento di posizione iscrivendosi a NavigationManager.LocationChanged.
Quando il framework chiama
HandleLocationChanged, il metodoDisposeviene scollegato. Scollegare il metodo consente la garbage collection del componente.L'implementazione del logger registra le informazioni seguenti quando viene selezionato il pulsante:
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;
}
Per altre informazioni sull'eliminazione dei componenti, vedere ASP.NET Core Razor eliminazione dei componenti.
Comportamento di reindirizzamento di Gestione spostamento durante il rendering lato server statico (SSR statico)
Per un reindirizzamento durante il rendering statico lato server (SSR statico), NavigationManager si basa sulla creazione di un NavigationException oggetto che viene acquisito dal framework, che converte l'errore in un reindirizzamento. Codice esistente dopo la chiamata a NavigateTo non viene chiamato. Quando si usa Visual Studio, il debugger interrompe l'eccezione, richiedendo di deselezionare la casella di controllo interruzione quando questo tipo di eccezione viene gestito dall'utente nell'interfaccia utente di Visual Studio per evitare l'arresto del debugger per i reindirizzamenti futuri.
È possibile usare la <BlazorDisableThrowNavigationException> proprietà MSBuild impostata su true nel file di progetto dell'app per acconsentire esplicitamente a non generare più un'eccezione NavigationException. Inoltre, il codice dopo la chiamata a NavigateTo viene eseguito quando non sarebbe stato eseguito in precedenza. Questo comportamento è abilitato per impostazione predefinita nel modello di progetto .NET 10 o versione successiva Blazor Web App :
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
Annotazioni
In .NET 10 o versioni successive è possibile acconsentire esplicitamente a non generare un'eccezione NavigationException impostando la <BlazorDisableThrowNavigationException> proprietà MSBuild su true nel file di progetto dell'app. Per sfruttare i vantaggi della nuova proprietà e del comportamento di MSBuild, aggiornare l'app a .NET 10 o versione successiva.
Risposte non trovate
NavigationManager fornisce un NotFound metodo per gestire gli scenari in cui una risorsa richiesta non viene trovata durante il rendering statico lato server (SSR statico) o il rendering interattivo globale:
SSR statico: la chiamata
NavigationManager.NotFoundimposta il codice di stato HTTP su 404.Rendering interattivo: segnala al router (Blazor) di eseguire il
Routerrendering del contenuto non trovato.Rendering streaming: Se la navigazione avanzata è attiva, il rendering streaming esegue il rendering del contenuto Non trovato senza ricaricare la pagina. Quando la navigazione avanzata è bloccata, il framework reindirizza al contenuto Non trovato con un aggiornamento della pagina.
Annotazioni
Nella discussione seguente viene indicato che un componente Not Found Razor può essere assegnato al parametro Router del componente NotFoundPage. Il parametro funziona insieme NavigationManager.NotFound a e viene descritto in modo più dettagliato più avanti in questa sezione.
Il rendering dello streaming può eseguire il rendering solo di componenti che hanno una route, come un'assegnazione (NotFoundPage) o un'assegnazione di pagina del middleware di riesecuzione delle pagine di codice di stato (NotFoundPage="...").
DefaultNotFound Il contenuto 404 ("Not found" testo normale) non ha una route, quindi non può essere usato durante il rendering dello streaming.
Annotazioni
Il frammento di rendering Non trovato (<NotFound>...</NotFound>) non è supportato in .NET 10 o versione successiva.
NavigationManager.NotFound il rendering del contenuto usa quanto segue, indipendentemente dal fatto che la risposta sia stata avviata o meno (in ordine):
- Se NotFoundEventArgs.Path è impostato, eseguire il rendering del contenuto della pagina assegnata.
- Se
Router.NotFoundPageè impostato, eseguire il rendering della pagina assegnata. - Pagina Middleware di ripetizione dell'esecuzione delle tabelle codici di stato, se configurata.
- Nessuna azione se non viene adottato nessuno degli approcci precedenti.
Il middleware di riesecuzione delle pagine di codice di stato con UseStatusCodePagesWithReExecute ha la precedenza per i problemi di routing degli indirizzi basati su browser, come un URL non corretto digitato nella barra degli indirizzi del browser o la selezione di un collegamento senza endpoint nell'app.
Quando viene eseguito il rendering statico di un componente (SSR statico) e NavigationManager.NotFound viene chiamato, il codice di stato 404 viene impostato sulla risposta:
@page "/render-not-found-ssr"
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NotFound();
}
}
Per fornire contenuto non trovato per il rendering interattivo globale, usare una pagina Non trovata (Razor componente).
Annotazioni
Il modello progetto di Blazor include una pagina NotFound.razor. Questa pagina esegue automaticamente il rendering ogni volta che NavigationManager.NotFound viene chiamato, rendendo possibile gestire le route mancanti con un'esperienza utente coerente.
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>
Il NotFound componente viene assegnato al parametro del NotFoundPage router.
NotFoundPage supporta il routing che può essere utilizzato nel middleware di riesecuzione delle pagine codici di stato, inclusi i middleware non-Blazor.
Nell'esempio seguente il componente precedente NotFound è presente nella cartella dell'app Pages e passato al NotFoundPage parametro :
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
</Router>
Quando viene eseguito il rendering di un componente con una modalità di rendering interattiva globale, la chiamata di NavigationManager.NotFound segnala al router Blazor di eseguire il rendering del componente 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();
}
}
È possibile usare l'evento OnNotFound per le notifiche quando NavigationManager.NotFound viene richiamato. L'evento viene attivato solo quando NavigationManager.NotFound viene chiamato, non per una risposta 404. Ad esempio, l'impostazione HttpContextAccessor.HttpContext.Response.StatusCode su 404 non attiva NavigationManager.NotFound/OnNotFound.
Anche le app che implementano un router personalizzato possono usare NavigationManager.NotFound. Il router personalizzato può visualizzare contenuti non trovati da due origini, in base allo stato della risposta ricevuta.
Indipendentemente dallo stato della risposta, il percorso di riesezione della pagina può essere usato passandolo a UseStatusCodePagesWithReExecute:
app.UseStatusCodePagesWithReExecute( "/not-found", createScopeForStatusCodePages: true);Quando la risposta è avviata, l'oggetto NotFoundEventArgs.Path può essere usato sottoscrivendo al
OnNotFoundEventnel router.@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; } } }
Nell'esempio seguente per i componenti che adottano il rendering interattivo lato server (SSR interattivo), il rendering del contenuto personalizzato viene eseguito a seconda della posizione in cui OnNotFound viene chiamato. Se l'evento viene attivato dal componente seguente Movie quando un filmato non viene trovato durante l'inizializzazione dei componenti, un messaggio personalizzato indica che il filmato richiesto non viene trovato. Se l'evento viene attivato dal User componente nell'esempio seguente, un messaggio diverso indica che l'utente non viene trovato.
Il servizio seguente NotFoundContext gestisce il contesto e il messaggio per quando il contenuto non viene trovato dai componenti.
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;
}
}
Il servizio viene registrato nel file Program lato server.
builder.Services.AddScoped<NotFoundContext>();
La pagina NotFound inietta NotFoundContext e visualizza l'intestazione e il messaggio.
Pages/NotFound.razor:
@page "/not-found"
@layout MainLayout
@inject NotFoundContext NotFoundContext
<h3>@NotFoundContext.Heading</h3>
<div>
<p>@NotFoundContext.Message</p>
</div>
Il componente Routes (Routes.razor) imposta il componente NotFound come pagina "Non trovato" tramite il parametro NotFoundPage.
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
...
</Router>
Nei componenti di esempio seguenti:
- Il
NotFoundContextservizio viene inserito insieme all'oggetto NavigationManager. - In OnInitializedAsync,
HandleNotFoundè un gestore eventi assegnato all'eventoOnNotFound.HandleNotFoundchiamaNotFoundContext.UpdateContextper impostare un'intestazione e un messaggio per il contenuto Non trovato nelNotFoundcomponente. - I componenti in genere usano un ID da un parametro di route per ottenere un filmato o un utente da un archivio dati, ad esempio un database. Negli esempi seguenti non viene restituita alcuna entità (
null) per simulare ciò che accade quando un'entità non viene trovata. - Quando non viene restituita alcuna entità a OnInitializedAsync,
NavigationManager.NotFoundviene chiamata , che a sua volta attiva l'eventoOnNotFounde ilHandleNotFoundgestore eventi. Il contenuto non trovato viene visualizzato dal router. - Il metodo
HandleNotFoundviene scollegato durante l'eliminazione del componente in 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; }
}
}
Per raggiungere i componenti precedenti in una dimostrazione locale con un'app di test, creare voci nel componente NavMenu (NavMenu.razor) per raggiungere i componenti Movie e User. Gli ID entità, passati come parametri di route, nell'esempio seguente sono valori fittizi che non hanno alcun effetto perché non vengono effettivamente usati dai componenti, che simulano di non trovare un filmato o un utente.
In 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>
Navigazione avanzata e gestione dei moduli
Questa sezione si applica a Blazor Web Apps.
Blazor Web Apps è in grado di eseguire due tipi di routing per lo spostamento di pagine e le richieste di gestione dei moduli:
- Navigazione normale (spostamento tra documenti): viene attivato un ricaricamento a pagina intera per l'URL della richiesta.
- Spostamento avanzato (navigazione nello stesso documento): Blazor intercetta la richiesta ed esegue invece una
fetchrichiesta. Blazor applica quindi patch al contenuto della risposta nel DOM della pagina. BlazorLa gestione avanzata dei moduli e della navigazione evita la necessità di ricaricare una pagina intera e mantiene più dello stato della pagina, quindi le pagine vengono caricate più velocemente, in genere senza perdere la posizione di scorrimento dell'utente nella pagina.
La navigazione avanzata è disponibile quando:
- Lo Blazor Web App script (
blazor.web.js) viene usato, non lo Blazor Server script (blazor.server.js) o lo Blazor WebAssembly script (blazor.webassembly.js). - La funzionalità non è esplicitamente disabilitata.
- L'URL di destinazione si trova all'interno dello spazio URI di base interno (percorso di base dell'app) e il collegamento alla pagina non ha l'attributo
data-enhance-navimpostato sufalse.
Se il routing sul lato server e la navigazione avanzata sono abilitati, i gestori di modifica della posizione vengono richiamati solo per la navigazione a livello di codice avviata da un runtime interattivo. Nelle versioni future, altri tipi di navigazione, ad esempio dopo un collegamento, possono anche richiamare gestori di modifica della posizione.
Quando si verifica un spostamento avanzato, LocationChanged i gestori eventi registrati con i runtime Interactive Server e WebAssembly vengono in genere richiamati. Esistono casi in cui i gestori di modifica della posizione potrebbero non intercettare una navigazione avanzata. Ad esempio, l'utente potrebbe passare a un'altra pagina prima che un runtime interattivo diventi disponibile. Pertanto, è importante che la logica dell'app non si basi sul richiamo di un gestore di modifica della posizione, poiché non esiste garanzia che venga eseguito.
Quando si chiama NavigateTo:
- Se
forceLoadèfalse, ovvero l'impostazione predefinita:- La navigazione avanzata è disponibile nell'URL corrente e viene attivata quella di Blazor.
- In caso contrario, Blazor esegue un ricaricamento completo della pagina per l'URL richiesto.
- Se
forceLoadètrue: Blazor esegue un ricaricamento a pagina intera per l'URL richiesto, indipendentemente dal fatto che lo spostamento avanzato sia disponibile o meno.
È possibile aggiornare la pagina corrente chiamando NavigationManager.Refresh(bool forceLoad = false), che esegue sempre una navigazione avanzata, se disponibile. Se la navigazione migliorata non è disponibile, Blazor esegue un ricaricamento a pagina intera.
Navigation.Refresh();
Passa true al parametro forceLoad per assicurarti che venga effettuato sempre un ricaricamento a pagina intera, anche se la navigazione potenziata è disponibile.
Navigation.Refresh(true);
La navigazione avanzata è abilitata per impostazione predefinita, ma può essere controllata gerarchicamente e per ogni collegamento usando l'attributo data-enhance-nav HTML.
Gli esempi seguenti disabilitano la navigazione avanzata:
<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 la destinazione è unBlazor endpoint diverso, lo spostamento avanzato non si applica e il JavaScript lato client riprova effettuando un caricamento completo della pagina. Questo assicura che non ci sia alcuna confusione nel framework riguardo alle pagine esterne che non dovrebbero essere integrate in una pagina esistente.
Per abilitare la gestione avanzata dei moduli, aggiungere il Enhance parametro ai EditForm moduli o all'attributo data-enhance ai moduli HTML (<form>):
<EditForm ... Enhance ...>
...
</EditForm>
<form ... data-enhance ...>
...
</form>
La gestione avanzata dei moduli non è gerarchica e non passa ai moduli figlio:
Non supportato: non è possibile impostare lo spostamento avanzato sull'elemento predecessore di un modulo per abilitare la navigazione avanzata per il modulo.
<div ... data-enhance ...>
<form ...>
<!-- NOT enhanced -->
</form>
</div>
I post di modulo avanzati funzionano solo con gli endpoint Blazor. La pubblicazione di un modulo avanzato su un endpoint non-Blazor genera un errore.
Per disabilitare la navigazione avanzata:
- Per un EditForm, rimuovere il parametro Enhance dall'elemento del modulo (o impostarlo su
false:Enhance="false"). - Per un codice HTML
<form>, rimuovere l'attributodata-enhancedall'elemento form (o impostarlo sufalse:data-enhance="false").
Se il contenuto aggiornato non fa parte del rendering del server, la navigazione migliorata e la gestione dei moduli possono annullare modifiche dinamiche al DOM. Per mantenere il contenuto di un elemento, usare l'attributo data-permanent .
Nell'esempio seguente il contenuto dell'elemento <div> viene aggiornato dinamicamente da uno script quando la pagina viene caricata:
<div data-permanent>
...
</div>
Una volta che Blazor è stato avviato sul client, è possibile usare l'evento enhancedload per ascoltare gli aggiornamenti di pagina avanzati. Ciò consente di riapplicare le modifiche al DOM che potrebbero essere state annullate da un aggiornamento di pagina avanzato.
Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));
Per disabilitare l'esplorazione avanzata e la gestione dei form a livello globale, vedere
La navigazione avanzata con il rendering statico lato server (static SSR) richiede particolare attenzione durante il caricamento di JavaScript. Per ulteriori informazioni, vedere ASP.NET Core Blazor JavaScript con il rendering statico lato server (SSR).
Produrre un URI relativo al prefisso URI di base
In base all'URI di base dell'app, ToBaseRelativePath converte un URI assoluto in un URI relativo al prefisso dell'URI di base.
Si consideri l'esempio seguente:
try
{
baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
...
}
Se l'URI di base dell'app è https://localhost:8000, vengono ottenuti i risultati seguenti:
- Il passaggio di
https://localhost:8000/segmentininputURIrestituisce unbaseRelativePathdisegment. - Il passaggio di
https://localhost:8000/segment1/segment2ininputURIrestituisce unbaseRelativePathdisegment1/segment2.
Se l'URI di base dell'app non corrisponde all'URI di base di inputURI, viene generata un'eccezione ArgumentException .
Il passaggio https://localhost:8001/segmentinputURI comporta l'eccezione seguente:
System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'
Stato della cronologia degli spostamenti
NavigationManager usa l'API Cronologia del browser per mantenere lo stato della cronologia di navigazione associato a ogni modifica della localizzazione apportata dall'applicazione. Mantenere lo stato della cronologia è particolarmente utile in scenari di reindirizzamento esterno, ad esempio quando si autentica gli utenti tramite provider di identità esterni. Per altre informazioni, vedere la sezione Opzioni di spostamento.
Opzioni di spostamento
Passare NavigationOptions a NavigateTo per controllare i comportamenti seguenti:
-
ForceLoad: ignorare il routing lato client e forzare il browser a caricare la nuova pagina dal server, indipendentemente dal fatto che l'URI sia gestito dal router lato client. Il valore predefinito è
false. -
ReplaceHistoryEntry: Sostituisce la voce corrente nello stack di cronologia. Se
false, aggiungi la nuova voce allo stack di cronologia. Il valore predefinito èfalse. - HistoryEntryState: ottiene o imposta lo stato da aggiungere alla voce della cronologia.
Navigation.NavigateTo("/path", new NavigationOptions
{
HistoryEntryState = "Navigation state"
});
Per altre informazioni su come ottenere lo stato associato alla voce della cronologia di destinazione durante la gestione delle modifiche della posizione, vedere la sezione Gestire/impedire modifiche alla posizione.
Parametri di query
Usare l'attributo [SupplyParameterFromQuery] per specificare che un parametro del componente proviene dalla stringa di query.
Utilizzare l'attributo
Annotazioni
I parametri del componente possono ricevere i valori dei parametri della query solo nei componenti instradabili tramite la direttiva @page.
Solo i componenti instradabili ricevono direttamente parametri di query per evitare di invertire il flusso di informazioni dall'alto verso il basso e rendere chiaro l'ordine di elaborazione dei parametri, sia dal framework che dall'app. Questa progettazione evita bug sottili nel codice dell'app scritto presupponendo un ordine di elaborazione dei parametri specifico. È possibile definire parametri a catena personalizzati o assegnare direttamente ai parametri dei componenti regolari per passare i valori dei parametri di query a componenti non instradabili.
I parametri del componente forniti dalla stringa di query supportano i tipi seguenti:
-
bool,DateTime, ,decimaldouble,float,Guid,int.longstring - Varianti annullabili dei tipi precedenti.
- Matrici dei tipi precedenti, che siano annullabili o non annullabili.
Viene applicata la corretta formattazione cultura-invariante per il tipo specificato (CultureInfo.InvariantCulture).
Specificare la proprietà [SupplyParameterFromQuery] dell'attributo Name per usare un nome di parametro di query diverso dal nome del parametro del componente. Nell'esempio seguente il nome C# del parametro del componente è {COMPONENT PARAMETER NAME}. È specificato un diverso nome di parametro di query per il segnaposto {QUERY PARAMETER NAME}.
A differenza delle proprietà dei parametri del componente ([Parameter]), [SupplyParameterFromQuery] le proprietà possono essere contrassegnate private oltre a public.
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }
Proprio come le proprietà dei parametri dei componenti ([Parameter]), le proprietà [SupplyParameterFromQuery] sono sempre proprietà public in .NET 6/7. In .NET 8 o versioni successive le [SupplyParameterFromQuery] proprietà possono essere contrassegnate public o private.
[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }
Nell'esempio seguente con un URL di /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman:
- La
Filterproprietà si risolve inscifi stars. - La
Pageproprietà si risolve in3. - La
Starsmatrice viene riempita dai parametri di query denominatistar(Name = "star") e viene risolta inLeVar BurtoneGary Oldman.
Annotazioni
I parametri della stringa di query nel componente pagina instradabile seguente funzionano anche in un componente non instradabile senza una @page direttiva, Search.razor ad esempio per un componente condiviso Search usato in altri componenti.
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; }
}
Usare GetUriWithQueryParameter per aggiungere, modificare o rimuovere uno o più parametri di query nell'URL corrente:
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})
Per l'esempio precedente:
- Il
{NAME}segnaposto specifica il nome del parametro di query. Il{VALUE}segnaposto specifica il valore come tipo supportato. I tipi supportati sono elencati più avanti in questa sezione. - Viene restituita una stringa uguale all'URL corrente con un singolo parametro:
- Aggiunto se il nome del parametro di query non esiste nell'URL corrente.
- Aggiornato al valore specificato se il parametro di query esiste nell'URL corrente.
- Rimosso se il tipo del valore specificato è nullable e il valore è
null.
- Viene applicata la corretta formattazione cultura-invariante per il tipo specificato (CultureInfo.InvariantCulture).
- Il nome e il valore del parametro di query sono codificati in URL.
- Tutti i valori con il nome del parametro di query corrispondente vengono sostituiti se sono presenti più istanze del tipo.
Chiamare GetUriWithQueryParameters per creare un URI costruito da Uri con più parametri aggiunti, aggiornati o rimossi. Per ogni valore, il framework usa value?.GetType() per determinare il tipo di esecuzione per ogni parametro di query e seleziona la formattazione cultura-invariante corretta. Il framework genera un errore per i tipi non supportati.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters({PARAMETERS})
Il segnaposto {PARAMETERS} è un IReadOnlyDictionary<string, object>.
Passare una stringa URI a GetUriWithQueryParameters per generare un nuovo URI da un URI fornito con più parametri aggiunti, aggiornati o rimossi. Per ogni valore, il framework usa value?.GetType() per determinare il tipo di esecuzione per ogni parametro di query e seleziona la formattazione cultura-invariante corretta. Il framework genera un errore per i tipi non supportati. I tipi supportati sono elencati più avanti in questa sezione.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
- Il
{URI}segnaposto è l'URI con o senza una stringa di query. - Il segnaposto
{PARAMETERS}è unIReadOnlyDictionary<string, object>.
I tipi supportati sono identici ai tipi supportati per i vincoli di route:
boolDateOnlyDateTimedecimaldoublefloatGuidintlongstringTimeOnly
I tipi supportati includono:
- Varianti annullabili dei tipi precedenti.
- Matrici dei tipi precedenti, che siano annullabili o non annullabili.
Avvertimento
Con la compressione, abilitata per impostazione predefinita, evitare di creare componenti interattivi lato server (autenticati/autorizzati) che effettuano il rendering dei dati provenienti da fonti non attendibili. Le origini non attendibili includono parametri di route, stringhe di query, dati di JS interoperabilità e qualsiasi altra origine di dati che un utente di terze parti può controllare (database, servizi esterni). Per ulteriori informazioni, consultare le linee guida di ASP.NET Core BlazorSignalR e le indicazioni sulla mitigazione delle minacce per il rendering lato server interattivo di ASP.NET CoreBlazor.
Sostituire un valore del parametro di query quando il parametro esiste
Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
| URL corrente | URL generato |
|---|---|
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 |
Aggiungere un parametro di query e un valore quando il parametro non esiste
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
| URL corrente | URL generato |
|---|---|
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 |
Rimuovere un parametro di query quando il valore del parametro è null
Navigation.GetUriWithQueryParameter("full name", (string)null)
| URL corrente | URL generato |
|---|---|
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/ |
Aggiungere, aggiornare e rimuovere parametri di query
Nell'esempio seguente :
- Se presente,
nameviene rimosso. -
ageviene aggiunto con un valore di25(int), se non presente. Se presente,ageviene aggiornato a un valore di25. -
eye colorviene aggiunto o aggiornato a un valore digreen.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["name"] = null,
["age"] = (int?)25,
["eye color"] = "green"
})
| URL corrente | URL generato |
|---|---|
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 |
Supporto per i valori enumerabili
Nell'esempio seguente :
-
full nameviene aggiunto o aggiornato aMorena Baccarin, un singolo valore. -
pingi parametri vengono aggiunti o sostituiti con35,1687e240.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["full name"] = "Morena Baccarin",
["ping"] = new int?[] { 35, 16, null, 87, 240 }
})
| URL corrente | URL generato |
|---|---|
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 |
Navigare con un parametro di query aggiunto o modificato
Per spostarsi con una stringa di query aggiunta o modificata, passare un URL generato a NavigateTo.
L'esempio seguente invoca:
-
GetUriWithQueryParameter per aggiungere o sostituire il
nameparametro di query usando un valore diMorena Baccarin. - Chiamate NavigateTo per attivare la navigazione al nuovo URL.
Navigation.NavigateTo(
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));
La stringa di query di una richiesta viene ottenuta dalla NavigationManager.Uri proprietà :
@inject NavigationManager Navigation
...
var query = new Uri(Navigation.Uri).Query;
Per analizzare i parametri di una stringa di query, un approccio consiste nell'usare URLSearchParams con l'interoperabilità di JavaScript (JS).
export createQueryString = (string queryString) => new URLSearchParams(queryString);
Per altre informazioni sull'isolamento JavaScript con i moduli JavaScript, vedere Chiamare le funzioni JavaScript dai metodi .NET in ASP.NET Core Blazor.
Passare a elementi denominati
Passare a un elemento nominato usando i seguenti approcci con un riferimento hash (#) all'elemento. I percorsi agli elementi all'interno del componente e quelli per gli elementi nei componenti esterni utilizzano percorsi relativi alla radice. Una barra iniziale (/) è facoltativa.
Esempi per ciascuno degli approcci seguenti illustrano la navigazione a un elemento con un id di targetElement nella componente Counter.
Elemento di ancoraggio (
<a>): conhref<a href="/counter#targetElement">NavLinkcomponente con :
href<NavLink href="/counter#targetElement">NavigationManager.NavigateTo passare l'URL relativo:
Navigation.NavigateTo("/counter#targetElement");
Nell'esempio seguente viene illustrato come navigare verso le intestazioni H2 intitolate all'interno di un componente e verso componenti esterni.
Home Nei componenti (Home.razor) e Counter (Counter.razor) posizionare il markup seguente nella parte inferiore del markup del componente esistente da utilizzare come destinazioni di navigazione. Il <div> crea spazio verticale artificiale per illustrare il comportamento di scorrimento del browser.
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
Aggiungere il componente seguente FragmentRouting all'app.
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");
}
}
Gestire/impedire modifiche alla posizione
RegisterLocationChangingHandler registra un gestore per elaborare gli eventi di navigazione in ingresso. Il contesto del gestore fornito da LocationChangingContext include le proprietà seguenti:
- TargetLocation: ottiene la posizione di destinazione.
- HistoryEntryState: Ottiene lo stato associato alla voce nella cronologia di riferimento.
- IsNavigationIntercepted: verifica se la navigazione è stata intercettata da un collegamento.
- CancellationToken: ottiene un CancellationToken per determinare se la navigazione è stata annullata, ad esempio per determinare se l'utente ha attivato una navigazione diversa.
- PreventNavigation: Chiamato per impedire che la navigazione continui.
Un componente può registrare più gestori di cambiamento della posizione nel metodo ciclo di vita
- Quando si selezionano collegamenti interni, ovvero collegamenti che puntano agli URL nel percorso di base dell'app.
- Durante lo spostamento tramite i pulsanti avanti e indietro in un browser.
Gli handler vengono eseguiti solo per la navigazione interna dell'app. Se l'utente seleziona un collegamento che passa a un sito diverso o modifica manualmente la barra degli indirizzi in un altro sito, i gestori di modifica della posizione non vengono eseguiti.
Implementare IDisposable ed eliminare i gestori registrati per annullarne la registrazione. Per ulteriori informazioni, vedere eliminazione dei componenti di ASP.NET Core Razor.
Importante
Non tentare di eseguire attività di pulizia DOM tramite JavaScript interop (JS) durante la gestione dei cambiamenti di posizione. Utilizzare il modello MutationObserver nel JS client. Per ulteriori informazioni, vedere ASP.NET Core Blazor interoperabilità di JavaScript (JS interop).
Nell'esempio seguente viene registrato un gestore del cambio di posizione per eventi di navigazione.
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();
}
Poiché la navigazione interna può essere annullata in modo asincrono, possono verificarsi più chiamate sovrapposte ai gestori registrati. Ad esempio, più chiamate di gestori possono verificarsi quando l'utente seleziona rapidamente il pulsante Indietro in una pagina o seleziona più collegamenti prima dell'esecuzione di una navigazione. Di seguito è riportato un riepilogo della logica di spostamento asincrona:
- Se vengono registrati gestori del cambiamento di posizione, tutta la navigazione viene inizialmente annullata, quindi ripetuta se la navigazione non viene annullata.
- Se vengono effettuate richieste di spostamento sovrapposte, la richiesta più recente annulla sempre le richieste precedenti, il che significa quanto segue:
- L'app può trattare più selezioni di pulsanti indietro e avanti come una singola selezione.
- Se l'utente seleziona più collegamenti prima del completamento della navigazione, l'ultimo collegamento selezionato determina lo spostamento.
Per ulteriori informazioni su come passare NavigationOptions a NavigateTo per controllare le voci e lo stato dello stack della cronologia di navigazione, consultare la sezione Opzioni di navigazione.
Per ulteriori esempi di codice, vedere il NavigationManagerComponent nel BasicTestApp (dotnet/aspnetcore origine di riferimento).
Annotazioni
In genere, i collegamenti della documentazione alla sorgente di riferimento .NET caricano il ramo predefinito del repository, che rappresenta lo sviluppo corrente per la versione successiva di .NET. Per selezionare un tag per una versione specifica, utilizzare il menu a tendina Seleziona rami o tag. Per ulteriori informazioni, vedere Come selezionare un tag di versione del codice sorgente di ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Il NavigationLock componente intercetta gli eventi di navigazione finché è renderizzato, "bloccando" qualsiasi navigazione data fino a quando non viene presa una decisione per procedere o annullare. Usare NavigationLock quando l'intercettazione della navigazione può essere limitata alla durata di un componente.
Parametri NavigationLock:
-
ConfirmExternalNavigation imposta una finestra di dialogo del browser per richiedere all'utente di confermare o annullare la navigazione esterna. Il valore predefinito è
false. La visualizzazione della finestra di dialogo di conferma richiede l'interazione iniziale dell'utente con la pagina prima di attivare lo spostamento esterno con l'URL nella barra degli indirizzi del browser. Per altre informazioni sul requisito di interazione, vedere Finestra:beforeunloadevento. - OnBeforeInternalNavigation definisce un callback per gli eventi di navigazione interna.
Nel componente NavLock seguente:
- Un tentativo di seguire il collegamento al sito Web di Microsoft deve essere confermato dall'utente prima che la navigazione
https://www.microsoft.comabbia esito positivo. viene chiamato per impedire l'esecuzione della navigazione se l'utente rifiuta di confermare la navigazione tramite una chiamata di interoperabilità JavaScript ( ) che genera la finestra di dialogo .
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();
}
}
}
Per ulteriori esempi di codice, vedere il componente ConfigurableNavigationLock nel BasicTestApp (dotnet/aspnetcore fonte di riferimento).
Componenti generati NavLink dinamicamente tramite reflection
NavLink Le voci dei componenti possono essere create dinamicamente dai componenti dell'app tramite reflection. Nell'esempio seguente viene illustrato l'approccio generale per un'ulteriore personalizzazione.
Per la dimostrazione seguente viene usata una convenzione di denominazione standard coerente per i componenti dell'app:
- I nomi dei file dei componenti instradabili usano la notazione Pascal, ad esempio
Pages/ProductDetail.razor. - I percorsi dei file dei componenti instradabili corrispondono ai rispettivi URL in formato "kebab case", con trattini visualizzati tra le parole nel modello di percorso di un componente. Ad esempio, un componente
ProductDetailcon un modello di route/product-detail(@page "/product-detail") viene richiesto in un browser nell'URL relativo/product-detail.
†Il Pascal case (Camel case maiuscolo) è una convenzione di scrittura senza spazi e punteggiatura, in cui la prima lettera di ogni parola è maiuscola, inclusa la prima parola.
*Kebab case è una convenzione di denominazione senza spazi e punteggiatura che usa lettere minuscole e trattini tra le parole.
Nel markup del componente RazorNavMenu (NavMenu.razor) sotto la pagina predefinita Home, i componenti NavLink vengono aggiunti da una raccolta:
<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>
Nel blocco GetRoutableComponents, il metodo @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);
L'esempio precedente non include le pagine seguenti nell'elenco di componenti di cui è stato eseguito il rendering:
-
Homepage: La pagina è elencata separatamente dai collegamenti generati automaticamente per apparire nella parte superiore dell'elenco e impostare il parametroMatch. -
Errorpage: la pagina di errore viene visualizzata solo dal framework e non deve essere elencata.
Per una dimostrazione del codice precedente in un'app di esempio, scaricare l'Blazor Web App o Blazor WebAssembly app di esempio.