Interoperabilità di JavaScript con Blazor

Completato

Blazor usa componenti C# anziché JavaScript per creare pagine Web o sezioni HTML con contenuto dinamico. Tuttavia, è possibile sfruttare l'interoperabilità JavaScript con Blazor (interoperabilità JS) per chiamare le librerie JavaScript nelle app Blazor e per chiamare funzioni JavaScript direttamente dal codice .NET C#.

In questa unità verrà descritto come chiamare JavaScript dal codice C# in una pagina Blazor e come richiamare i metodi C# dalle funzioni JavaScript. Nella prossima unità, verrà usato un componente di avviso da una libreria JavaScript per aggiornare il sito Web di Blazor dedicato alla consegna delle pizze.

Usare l’interoperabilità di JavaScript con Blazor

Un tipico componente Blazor usa il layout e la logica dell'interfaccia utente per eseguire il rendering dell'HTML in fase di runtime. L’utente usa il codice C# per gestire eventi e altre funzioni dinamiche di una pagina che interagiscono con l'utente e con servizi esterni. In molti casi, non è necessario usare il codice JavaScript. Invece, è possibile usare Blazor con librerie .NET, che offrono molte funzionalità equivalenti.

Tuttavia, a volte è necessario usare una libreria JavaScript esistente. Ad esempio, alcune librerie JavaScript open source eseguono il rendering dei componenti e gestiscono gli elementi dell'interfaccia utente in modo specializzato. Potrebbe anche essere disponibile del codice JavaScript provato e testato che si preferisce riutilizzare, anziché convertirlo in C#.

È possibile integrare le librerie JavaScript nelle applicazioni usando l'interoperabilità di JavaScript con Blazor o l'interoperabilità JS. È possibile usare l'interoperabilità JS per chiamare funzioni JavaScript dai metodi .NET e richiamare i metodi .NET dalle funzioni JavaScript. L'interoperabilità JS gestisce il marshalling dei dati e dei riferimenti agli oggetti tra Blazor e JavaScript per facilitare la transizione tra di loro.

Caricare il codice JavaScript in un'app Blazor

JavaScript a un'app Blazor viene aggiunto allo stesso modo in cui lo si aggiunge a un'app Web HTML standard usando l'elemento HTML <script>. Il tag <script> va inserito dopo il tag esistente <script src="_framework/blazor.*.js"></script> nel file Pages/_Host.cshtml o nel file wwwroot/index.html, a seconda del modello di hosting Blazor utilizzato. Per altre informazioni, vedere Modelli di hosting ASP.NET Core Blazor.

È consigliabile non inserire script nell'elemento <head> della pagina. Poiché Blazor ha solo il controllo sul contenuto nell'elemento <body> di una pagina HTML, l'interoperabilità JS può non riuscire se gli script dipendono da Blazor. Inoltre, la pagina potrebbe essere visualizzata più lentamente a causa del tempo necessario per analizzare il codice JavaScript.

Il tag <script> funziona come in un'app Web HTML. È possibile scrivere codice direttamente nel corpo del tag oppure fare riferimento a un file JavaScript esistente. Per altre informazioni, vedere Interoperabilità JavaScript (interoperabilità JS) di ASP.NET Core Blazor: percorso di JavaScript.

Importante

Inserire i file JavaScript nella cartella wwwroot del progetto Blazor.

Un'altra opzione consiste nell'inserire un elemento <script> che fa riferimento a un file JavaScript nella pagina Pages/_Host.cshtml in modo dinamico. Questo approccio è utile quando è necessario caricare script diversi, a seconda delle condizioni che possono essere determinate solo in fase di runtime. Questo approccio può anche accelerare il caricamento iniziale dell'app se si attiva la logica con un evento che viene attivato dopo il rendering di una pagina. Per altre informazioni, vedere Avvio di ASP.NET Core Blazor.

Chiamare JavaScript dal codice .NET

Viene usato IJSRuntime per chiamare una funzione JavaScript dal codice .NET. Per rendere disponibile il runtime di interoperabilità JS, inserire un'istanza dell'astrazione IJSRuntime in una pagina Blazor, dopo la direttiva @page vicino l'inizio del file.

L'interfaccia IJSRuntime espone i metodi InvokeAsync e InvokeVoidAsync per richiamare il codice JavaScript. Usare InvokeAsync<TValue> per chiamare una funzione JavaScript che restituisce un valore. In caso contrario, chiamare InvokeVoidAsync. Come suggeriscono i nomi, entrambi i metodi sono asincroni. Per questa ragione, usare l'operatore await C# per acquisire i risultati.

Il parametro del metodo InvokeAsync o InvokeVoidAsync è il nome della funzione JavaScript da richiamare, seguito dai argomenti richiesti dalla funzione. La funzione JavaScript deve essere parte dell'ambito window o di un ambito secondario di window. Gli argomenti devono poter essere serializzati in formato JSON.

Nota

L'interoperabilità JS è disponibile solo quando l'app Blazor Server ha stabilito una connessione SignalR con il browser. Non è possibile effettuare chiamate di interoperabilità fino a quando non viene completato il rendering. Per rilevare se il rendering è stato completato, usare l'evento OnAfterRender o OnAfterRenderAsync nel codice Blazor.

Usare un oggetto ElementReference per aggiornare il DOM

Blazor mantiene una rappresentazione del DOM (Document Object Model) come albero di rendering virtuale. Man mano che la struttura della pagina cambia, Blazor genera un nuovo albero di rendering che contiene le differenze. Al termine delle modifiche, Blazor esegue l'iterazione delle differenze per aggiornare la visualizzazione dell'interfaccia utente nel browser e la versione del DOM usata da JavaScript.

Per il rendering degli elementi di una pagina sono disponibili molte librerie JavaScript di terze parti, che possono aggiornare il DOM. Se il codice JavaScript modifica gli elementi del DOM, la copia Blazor del DOM potrebbe non corrispondere più allo stato corrente. Questa situazione può causare un comportamento imprevisto e introdurre rischi per la sicurezza. È importante non apportare modifiche che possono causare il danneggiamento della visualizzazione Blazor del DOM.

Il modo più semplice per gestire questa situazione consiste nel creare un elemento segnaposto nel componente Blazor, di solito un elemento <div @ref="placeHolder"></div> vuoto. Il codice Blazor interpreta il codice come spazio vuoto e l'albero di rendering Blazor non tenta di tenere traccia dei contenuti. È possibile aggiungere liberamente elementi di codice JavaScript a questo <div> e Blazor non tenta di modificarlo.

Il codice dell'app Blazor definisce un campo di tipo ElementReference per contenere il riferimento all'elemento <div>. L'attributo @ref nell'elemento <div> imposta il valore del campo. L'oggetto ElementReference passa quindi a una funzione JavaScript, che può usare il riferimento per aggiungere contenuto all'elemento <div>.

Chiamare il codice .NET da JavaScript

Il codice JavaScript può eseguire un metodo .NET definito dal codice Blazor usando la classe di utilità DotNet, parte della libreria di interoperabilità JS. La classe DotNet espone le funzione helper invokeMethod e invokeMethodAsync. Usare invokeMethod per eseguire un metodo e attendere il risultato o usare invokeMethodAsync per chiamare il metodo in modo asincrono. Il metodo invokeMethodAsync restituisce un Promise JavaScript.

Suggerimento

Per mantenere la velocità di risposta nelle applicazioni, definire il metodo .NET come async e chiamarlo usando invokeMethodAsync da JavaScript.

È necessario contrassegnare il metodo .NET chiamato con JSInvokableAttribute. Il metodo deve essere public e tutti i parametri devono essere serializzabili come JSON. Inoltre, per un metodo asincrono, il tipo restituito deve essere void, Task o un oggetto generico Task<T> dove T è un tipo serializzabile JSON.

Per chiamare un metodo static, specificare il nome dell'assembly .NET che contiene la classe, un identificatore per il metodo e i parametri che il metodo accetta come argomenti della funzione invokeMethod o invokeMethodAsync. Per impostazione predefinita, l'identificatore del metodo corrisponde al nome del metodo, ma è possibile specificare un valore diverso usando l'attributo JSInvokable.

Chiamare un metodo di istanza .NET da JavaScript

Per eseguire un metodo di istanza, JavaScript richiede un riferimento all'oggetto che punta all'istanza. L'interoperabilità JS fornisce il tipo DotNetObjectReference generico che è possibile usare per creare un riferimento all'oggetto nel codice .NET. Il codice deve rendere disponibile il riferimento all'oggetto per JavaScript.

Il codice JavaScript può quindi chiamare invokeMethodAsync con il nome del metodo .NET e qualsiasi parametro richiesto dal metodo. Per evitare perdite di memoria, il codice .NET deve eliminare il riferimento all'oggetto quando non è più necessario.

Verificare le conoscenze

1.

Dove si deve aggiungere il tag script per fare riferimento a un file JavaScript incluso in Blazor?

2.

Quale metodo C# si deve usare per eseguire una funzione JavaScript che restituisce void?