Interoperabilità JavaScript [JSImport]
/[JSExport]
con ASP.NET Core Blazor
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere Criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 8 di questo articolo.
Questo articolo illustra come interagire con JavaScript (JS) nei componenti lato client usando l'API di interoperabilità JavaScript (JS) [JSImport]
/[JSExport]
rilasciata per le app che adottano .NET 7 o versioni successive.
Blazor fornisce il proprio JS meccanismo di interoperabilità basato sull'interfaccia IJSRuntime . BlazorL'interoperabilità di JS è supportata in modo uniforme tra Blazor le modalità di rendering e per Blazor Hybrid le app. IJSRuntimeconsente anche agli autori di librerie di creare JS librerie di interoperabilità per la condivisione nell'ecosistema e rimane l'approccio consigliato per JS l'interoperabilità Blazor in Blazor. Fai riferimento ai seguenti articoli:
- Chiamare funzioni JavaScript da metodi .NET in ASP.NET Core Blazor
- Chiamare metodi .NET da funzioni JavaScript in ASP.NET Core Blazor
Questo articolo descrive un approccio di interoperabilità alternativo JS specifico per i componenti lato client eseguiti in WebAssembly. Questi approcci sono appropriati quando si prevede solo l'esecuzione su WebAssembly sul lato client. Gli autori di librerie possono usare questi approcci per ottimizzare JS l'interoperabilità controllando durante l'esecuzione del codice se l'app è in esecuzione in WebAssembly in un browser (OperatingSystem.IsBrowser). Gli approcci descritti in questo articolo devono essere usati per sostituire l'API obsoleta di interoperabilità nonmarshalled JS durante la migrazione a .NET 7 o versione successiva.
Nota
Questo articolo è incentrato sull'interoperabilità JS nei componenti lato client. Per indicazioni sulla chiamata di .NET nelle app JavaScript, vedere Eseguire .NET da JavaScript.
API di interoperabilità JavaScript obsoleta
L'interoperabilità non interrotta JS con l'API IJSUnmarshalledRuntime è obsoleta in ASP.NET Core in .NET 7 o versione successiva. Seguire le indicazioni riportate in questo articolo per sostituire l'API obsoleta.
Prerequisiti
Scaricare e installare .NET 7 o versione successiva se non è già installato nel sistema o se il sistema non ha installato la versione più recente.
Spazio dei nomi
L'API JS di interoperabilità (JSHost.ImportAsync) descritta in questo articolo è controllata dagli attributi nello spazio dei System.Runtime.InteropServices.JavaScript nomi .
Abilitare blocchi non sicuri
Abilitare la AllowUnsafeBlocks proprietà nel file di progetto dell'app, che consente al generatore di codice nel compilatore Roslyn di usare i puntatori per JS l'interoperabilità:
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Avviso
L'API di interoperabilità richiede l'abilitazione JS di AllowUnsafeBlocks. Prestare attenzione quando si implementa codice non sicuro nelle app .NET, che possono introdurre rischi per la sicurezza e la stabilità. Per altre informazioni, vedere Codice unsafe, tipi di puntatore e puntatori a funzione.
Razor La libreria di classi (RCL) non JS è supportata
In genere, il supporto della posizione per l'interoperabilità JS basata su JS javaScript (posizione JavaScript nelle app ASP.NET CoreBlazor) è presente anche per l'interoperabilità [JSImport]
/[JSExport]
descritta in questo articolo.IJSRuntime L'unica funzionalità di posizione non supportata JS è per la collocazione JS in una libreria di Razor classi (RCL).
Invece di usare collocati JS in un RCL, posizionare il JS file nella cartella rcl wwwroot
e farvi riferimento usando il percorso consueto per gli asset statici RCL:
_content/{PACKAGE ID}/{PATH}/{FILE NAME}.js
- Il
{PACKAGE ID}
segnaposto è l'identificatore del pacchetto rcl (o il nome della libreria per una libreria di classi). - Il
{PATH}
segnaposto è il percorso del file. - Il
{FILE NAME}
segnaposto è il nome del file.
Anche se la collocazione JS in un rcl non è supportata dall'interoperabilità[JSExport]
[JSImport]
/, è possibile mantenere organizzati i JS file adottando uno o entrambi gli approcci seguenti:
- Assegnare al JS file lo stesso nome del componente in cui viene usato .JS Per un componente nell'RCL denominato
CallJavaScriptFromLib
(CallJavaScriptFromLib.razor
), denominare il fileCallJavaScriptFromLib.js
nellawwwroot
cartella . - Inserire i file specifici JS del componente in una
Components
cartella all'interno della cartella RCLwwwroot
e usare "Components
" nel percorso del file:_content/{PACKAGE ID}/Components/CallJavaScriptFromLib.js
.
Chiamare JavaScript da .NET
Questa sezione illustra come chiamare JS le funzioni da .NET.
Nel componente CallJavaScript1
seguente:
- Il
CallJavaScript1
modulo viene importato in modo asincrono dal file collocato JS con JSHost.ImportAsync. - La funzione importata
getMessage
JS viene chiamata daGetWelcomeMessage
. - La stringa del messaggio di benvenuto restituita viene visualizzata nell'interfaccia utente tramite il
message
campo .
CallJavaScript1.razor
:
@page "/call-javascript-1"
@rendermode InteractiveWebAssembly
@using System.Runtime.InteropServices.JavaScript
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call JS Example 1)
</h1>
@(message is not null ? message : string.Empty)
@code {
private string? message;
protected override async Task OnInitializedAsync()
{
await JSHost.ImportAsync("CallJavaScript1",
"../Components/Pages/CallJavaScript1.razor.js");
message = GetWelcomeMessage();
}
}
@page "/call-javascript-1"
@using System.Runtime.InteropServices.JavaScript
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call JS Example 1)
</h1>
@(message is not null ? message : string.Empty)
@code {
private string? message;
protected override async Task OnInitializedAsync()
{
await JSHost.ImportAsync("CallJavaScript1",
"../Pages/CallJavaScript1.razor.js");
message = GetWelcomeMessage();
}
}
Nota
Includere un controllo condizionale nel codice con OperatingSystem.IsBrowser per assicurarsi che l'interoperabilità JS venga chiamata solo da un componente sottoposto a rendering sul client. Questo aspetto è importante per le librerie/pacchetti NuGet destinati ai componenti lato server, che non possono eseguire il codice fornito da questa JS API di interoperabilità.
Per importare una JS funzione per chiamarla da C#, usare l'attributo [JSImport]
in una firma del metodo C# corrispondente alla JS firma della funzione. Il primo parametro dell'attributo [JSImport]
è il nome della JS funzione da importare e il secondo parametro è il nome del JS modulo.
Nell'esempio seguente è getMessage
una JS funzione che restituisce un string
oggetto per un modulo denominato CallJavaScript1
. La firma del metodo C# corrisponde a: nessun parametro viene passato alla JS funzione e la JS funzione restituisce un oggetto string
. La JS funzione viene chiamata da GetWelcomeMessage
nel codice C#.
CallJavaScript1.razor.cs
:
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;
namespace BlazorSample.Components.Pages;
[SupportedOSPlatform("browser")]
public partial class CallJavaScript1
{
[JSImport("getMessage", "CallJavaScript1")]
internal static partial string GetWelcomeMessage();
}
Lo spazio dei nomi dell'app per la classe parziale precedente CallJavaScript1
è BlazorSample
. Lo spazio dei nomi del componente è BlazorSample.Components.Pages
. Se si usa il componente precedente in un'app di test locale, aggiornare lo spazio dei nomi in modo che corrisponda all'app. Ad esempio, lo spazio dei nomi è ContosoApp.Components.Pages
se lo spazio dei nomi dell'app è ContosoApp
. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;
namespace BlazorSample.Pages;
[SupportedOSPlatform("browser")]
public partial class CallJavaScript1
{
[JSImport("getMessage", "CallJavaScript1")]
internal static partial string GetWelcomeMessage();
}
Lo spazio dei nomi dell'app per la classe parziale precedente CallJavaScript1
è BlazorSample
. Lo spazio dei nomi del componente è BlazorSample.Pages
. Se si usa il componente precedente in un'app di test locale, aggiornare lo spazio dei nomi in modo che corrisponda all'app. Ad esempio, lo spazio dei nomi è ContosoApp.Pages
se lo spazio dei nomi dell'app è ContosoApp
. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.
Nella firma del metodo importato è possibile usare i tipi .NET per i parametri e i valori restituiti, che vengono eseguiti automaticamente dal runtime. Usare JSMarshalAsAttribute<T> per controllare la modalità di marshalling dei parametri del metodo importato. Ad esempio, è possibile scegliere di effettuare il marshalling di System.Runtime.InteropServices.JavaScript.JSType.Number come long
o System.Runtime.InteropServices.JavaScript.JSType.BigInt. È possibile passare Action/Func<TResult> i callback come parametri, che vengono marshallati come funzioni chiamabili JS . È possibile passare JS riferimenti a oggetti gestiti e vengono sottoposto a marshalling come oggetti proxy, mantenendo attivo l'oggetto oltre il limite fino a quando il proxy non viene sottoposto a Garbage Collection. È anche possibile importare ed esportare metodi asincroni con un Task risultato, di cui viene eseguito il marshalling come JS promesse. La maggior parte dei tipi con marshalling funziona in entrambe le direzioni, come parametri e come valori restituiti, sia nei metodi importati che in quello esportato, illustrati nella sezione Chiamare .NET da JavaScript più avanti in questo articolo.
La tabella seguente indica i mapping dei tipi supportati.
.NET | JavaScript | Nullable |
Task ➔A Promise |
JSMarshalAs opzionale |
Array of |
---|---|---|---|---|---|
Boolean |
Boolean |
Supportata | Supportata | Supportata | Non supportato |
Byte |
Number |
Supportata | Supportata | Supportata | Supportata |
Char |
String |
Supportata | Supportata | Supportata | Non supportato |
Int16 |
Number |
Supportata | Supportata | Supportata | Non supportato |
Int32 |
Number |
Supportata | Supportata | Supportata | Supportata |
Int64 |
Number |
Supportata | Supportata | Non supportato | Non supportato |
Int64 |
BigInt |
Supportata | Supportata | Non supportato | Non supportato |
Single |
Number |
Supportata | Supportata | Supportata | Non supportato |
Double |
Number |
Supportata | Supportata | Supportata | Supportata |
IntPtr |
Number |
Supportata | Supportata | Supportata | Non supportato |
DateTime |
Date |
Supportata | Supportata | Non supportato | Non supportato |
DateTimeOffset |
Date |
Supportata | Supportata | Non supportato | Non supportato |
Exception |
Error |
Non supportato | Supportata | Supportata | Non supportato |
JSObject |
Object |
Non supportato | Supportata | Supportata | Supportata |
String |
String |
Non supportato | Supportata | Supportata | Supportata |
Object |
Any |
Non supportato | Supportata | Non supportato | Supportata |
Span<Byte> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
Span<Int32> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
Span<Double> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
ArraySegment<Byte> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
ArraySegment<Int32> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
ArraySegment<Double> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
Task |
Promise |
Non supportato | Non supportato | Supportata | Non supportato |
Action |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Action<T1> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Action<T1, T2> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Action<T1, T2, T3> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<T1, TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<T1, T2, TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<T1, T2, T3, TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Le condizioni seguenti si applicano al mapping dei tipi e ai valori con marshalling:
- La
Array of
colonna indica se il tipo .NET può essere sottoposto a marshalling come JSArray
. Esempio: C#int[]
(Int32
) mappato a JSArray
sNumber
. - Quando si passa un JS valore a C# con un valore di tipo errato, il framework genera un'eccezione nella maggior parte dei casi. Il framework non esegue il controllo dei tipi in fase di compilazione in JS.
JSObject
,Exception
Task
eArraySegment
creareGCHandle
e un proxy. È possibile attivare l'eliminazione nel codice dello sviluppatore o consentire a .NET Garbage Collection (GC) di eliminare gli oggetti in un secondo momento. Questi tipi comportano un sovraccarico significativo delle prestazioni.Array
: il marshalling di una matrice crea una copia della matrice in JS o .NET.MemoryView
MemoryView
è una JS classe per il runtime .NET WebAssembly di effettuare il marshallingSpan
eArraySegment
.- A differenza del marshalling di una matrice, il marshalling di un
Span
oggetto oArraySegment
non crea una copia della memoria sottostante. MemoryView
può essere creata correttamente dall'istanza del runtime .NET WebAssembly. Non è quindi possibile importare una JS funzione come metodo .NET con un parametro diSpan
oArraySegment
.MemoryView
creato per unSpan
oggetto è valido solo per la durata della chiamata di interoperabilità. PoichéSpan
viene allocato nello stack di chiamate, che non viene salvato in modo permanente dopo la chiamata di interoperabilità, non è possibile esportare un metodo .NET che restituisce un oggettoSpan
.MemoryView
creato per un oggettoArraySegment
sopravvive dopo la chiamata di interoperabilità ed è utile per la condivisione di un buffer. La chiamatadispose()
a unMemoryView
oggetto creato per unArraySegment
oggetto elimina il proxy e rimuove la matrice .NET sottostante. È consigliabile chiamaredispose()
in untry-finally
blocco perMemoryView
.
La tabella seguente indica i mapping dei tipi supportati.
.NET | JavaScript | Nullable |
Task ➔A Promise |
JSMarshalAs opzionale |
Array of |
---|---|---|---|---|---|
Boolean |
Boolean |
Supportata | Supportata | Supportata | Non supportato |
Byte |
Number |
Supportata | Supportata | Supportata | Supportata |
Char |
String |
Supportata | Supportata | Supportata | Non supportato |
Int16 |
Number |
Supportata | Supportata | Supportata | Non supportato |
Int32 |
Number |
Supportata | Supportata | Supportata | Supportata |
Int64 |
Number |
Supportata | Supportata | Non supportato | Non supportato |
Int64 |
BigInt |
Supportata | Supportata | Non supportato | Non supportato |
Single |
Number |
Supportata | Supportata | Supportata | Non supportato |
Double |
Number |
Supportata | Supportata | Supportata | Supportata |
IntPtr |
Number |
Supportata | Supportata | Supportata | Non supportato |
DateTime |
Date |
Supportata | Supportata | Non supportato | Non supportato |
DateTimeOffset |
Date |
Supportata | Supportata | Non supportato | Non supportato |
Exception |
Error |
Non supportato | Supportata | Supportata | Non supportato |
JSObject |
Object |
Non supportato | Supportata | Supportata | Supportata |
String |
String |
Non supportato | Supportata | Supportata | Supportata |
Object |
Any |
Non supportato | Supportata | Non supportato | Supportata |
Span<Byte> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
Span<Int32> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
Span<Double> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
ArraySegment<Byte> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
ArraySegment<Int32> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
ArraySegment<Double> |
MemoryView |
Non supportato | Non supportato | Non supportato | Non supportato |
Task |
Promise |
Non supportato | Non supportato | Supportata | Non supportato |
Action |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Action<T1> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Action<T1, T2> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Action<T1, T2, T3> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<T1, TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<T1, T2, TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Func<T1, T2, T3, TResult> |
Function |
Non supportato | Non supportato | Non supportato | Non supportato |
Le condizioni seguenti si applicano al mapping dei tipi e ai valori con marshalling:
- La
Array of
colonna indica se il tipo .NET può essere sottoposto a marshalling come JSArray
. Esempio: C#int[]
(Int32
) mappato a JSArray
sNumber
. - Quando si passa un JS valore a C# con un valore di tipo errato, il framework genera un'eccezione nella maggior parte dei casi. Il framework non esegue il controllo dei tipi in fase di compilazione in JS.
JSObject
,Exception
Task
eArraySegment
creareGCHandle
e un proxy. È possibile attivare l'eliminazione nel codice dello sviluppatore o consentire a .NET Garbage Collection (GC) di eliminare gli oggetti in un secondo momento. Questi tipi comportano un sovraccarico significativo delle prestazioni.Array
: il marshalling di una matrice crea una copia della matrice in JS o .NET.MemoryView
MemoryView
è una JS classe per il runtime .NET WebAssembly di effettuare il marshallingSpan
eArraySegment
.- A differenza del marshalling di una matrice, il marshalling di un
Span
oggetto oArraySegment
non crea una copia della memoria sottostante. MemoryView
può essere creata correttamente dall'istanza del runtime .NET WebAssembly. Non è quindi possibile importare una JS funzione come metodo .NET con un parametro diSpan
oArraySegment
.MemoryView
creato per unSpan
oggetto è valido solo per la durata della chiamata di interoperabilità. PoichéSpan
viene allocato nello stack di chiamate, che non viene salvato in modo permanente dopo la chiamata di interoperabilità, non è possibile esportare un metodo .NET che restituisce un oggettoSpan
.MemoryView
creato per un oggettoArraySegment
sopravvive dopo la chiamata di interoperabilità ed è utile per la condivisione di un buffer. La chiamatadispose()
a unMemoryView
oggetto creato per unArraySegment
oggetto elimina il proxy e rimuove la matrice .NET sottostante. È consigliabile chiamaredispose()
in untry-finally
blocco perMemoryView
.
Il nome del modulo nell'attributo [JSImport]
e la chiamata per caricare il modulo nel componente con JSHost.ImportAsync deve corrispondere e essere univoco nell'app. Quando si crea una libreria per la distribuzione in un pacchetto NuGet, è consigliabile usare lo spazio dei nomi del pacchetto NuGet come prefisso nei nomi dei moduli. Nell'esempio seguente il nome del modulo riflette il Contoso.InteropServices.JavaScript
pacchetto e una cartella di classi di interoperabilità dei messaggi utente (UserMessages
):
[JSImport("getMessage",
"Contoso.InteropServices.JavaScript.UserMessages.CallJavaScript1")]
Le funzioni accessibili nello spazio dei nomi globale possono essere importate usando il globalThis
prefisso nel nome della funzione e usando l'attributo [JSImport]
senza specificare un nome di modulo. Nell'esempio seguente, console.log
è preceduto da globalThis
. La funzione importata viene chiamata dal metodo C# Log
, che accetta un messaggio stringa C# (message
) e esegue il marshalling della stringa C# in un JSString
per console.log
:
[JSImport("globalThis.console.log")]
internal static partial void Log([JSMarshalAs<JSType.String>] string message);
Esportare script da un modulo JavaScript ES6 standard collocato con un componente o inserito con altri asset statici JavaScript in un JS file ( ad esempio , wwwroot/js/{FILE NAME}.js
dove JS gli asset statici vengono mantenuti in una cartella denominata js
nella cartella dell'app wwwroot
e il {FILE NAME}
segnaposto è il nome file).
Nell'esempio seguente una JS funzione denominata getMessage
viene esportata da un file collocato JS che restituisce un messaggio di benvenuto, "Hello from Blazor!" in portoghese:
CallJavaScript1.razor.js
:
export function getMessage() {
return 'Olá do Blazor!';
}
Chiamare .NET da JavaScript
Questa sezione illustra come chiamare i metodi .NET da JS.
Il componente seguente CallDotNet1
chiama JS che interagisce direttamente con il DOM per eseguire il rendering della stringa del messaggio di benvenuto:
- Il
CallDotNet
JS modulo viene importato in modo asincrono dal file collocato JS per questo componente. - La funzione importata
setMessage
JS viene chiamata daSetWelcomeMessage
. - Il messaggio di benvenuto restituito viene visualizzato dall'interfaccia
setMessage
utente tramite ilmessage
campo .
Importante
Nell'esempio di questa sezione viene JS usata l'interoperabilità per modificare un elemento DOM esclusivamente a scopo dimostrativo dopo il rendering del componente in OnAfterRender
. In genere, è consigliabile modificare il DOM solo con JS quando l'oggetto non interagisce con Blazor. L'approccio illustrato in questa sezione è simile ai casi in cui una libreria di terze parti JS viene usata in un Razor componente, in cui il componente interagisce con la JS libreria tramite JS interoperabilità, la libreria di terze parti JS interagisce con parte del DOM e Blazor non è coinvolta direttamente con gli aggiornamenti DOM a tale parte del DOM. Per altre informazioni, vedere ASP.NET Core JavaScript interoperabilità (interoperabilità).For more information, see ASP.NET Core Blazor JavaScript interoperability (JS interop).
CallDotNet1.razor
:
@page "/call-dotnet-1"
@rendermode InteractiveWebAssembly
@using System.Runtime.InteropServices.JavaScript
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call .NET Example 1)
</h1>
<p>
<span id="result">.NET method not executed yet</span>
</p>
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSHost.ImportAsync("CallDotNet1",
"../Components/Pages/CallDotNet1.razor.js");
SetWelcomeMessage();
}
}
}
@page "/call-dotnet-1"
@using System.Runtime.InteropServices.JavaScript
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call .NET Example 1)
</h1>
<p>
<span id="result">.NET method not executed yet</span>
</p>
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSHost.ImportAsync("CallDotNet1",
"../Pages/CallDotNet1.razor.js");
SetWelcomeMessage();
}
}
}
Per esportare un metodo .NET in modo che possa essere chiamato da JS, usare l'attributo[JSExport]
.
Nell'esempio seguente :
SetWelcomeMessage
chiama una JS funzione denominatasetMessage
. La JS funzione chiama in .NET per ricevere il messaggio di benvenuto daGetMessageFromDotnet
e visualizza il messaggio nell'interfaccia utente.GetMessageFromDotnet
è un metodo .NET con l'attributo[JSExport]
che restituisce un messaggio di benvenuto, "Hello from Blazor!" in portoghese.
CallDotNet1.razor.cs
:
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;
namespace BlazorSample.Components.Pages;
[SupportedOSPlatform("browser")]
public partial class CallDotNet1
{
[JSImport("setMessage", "CallDotNet1")]
internal static partial void SetWelcomeMessage();
[JSExport]
internal static string GetMessageFromDotnet()
{
return "Olá do Blazor!";
}
}
Lo spazio dei nomi dell'app per la classe parziale precedente CallDotNet1
è BlazorSample
. Lo spazio dei nomi del componente è BlazorSample.Components.Pages
. Se si usa il componente precedente in un'app di test locale, aggiornare lo spazio dei nomi dell'app in modo che corrisponda all'app. Ad esempio, lo spazio dei nomi del componente è ContosoApp.Components.Pages
se lo spazio dei nomi dell'app è ContosoApp
. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.
Nell'esempio seguente viene importata una JS funzione denominata setMessage
da un file collocato JS .
Il metodo setMessage
:
- Chiama
globalThis.getDotnetRuntime(0)
per esporre l'istanza di runtime .NET di WebAssembly per chiamare i metodi .NET esportati. - Ottiene le esportazioni dell'assembly dell'app JS . Il nome dell'assembly dell'app nell'esempio seguente è
BlazorSample
. - Chiama il
BlazorSample.Components.Pages.CallDotNet1.GetMessageFromDotnet
metodo dalle esportazioni (exports
). Il valore restituito, ovvero il messaggio di benvenuto, viene assegnato alCallDotNet1
testo del<span>
componente. Lo spazio dei nomi dell'app èBlazorSample
e loCallDotNet1
spazio dei nomi del componente èBlazorSample.Components.Pages
.
CallDotNet1.razor.js
:
export async function setMessage() {
const { getAssemblyExports } = await globalThis.getDotnetRuntime(0);
var exports = await getAssemblyExports("BlazorSample.dll");
document.getElementById("result").innerText =
exports.BlazorSample.Components.Pages.CallDotNet1.GetMessageFromDotnet();
}
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;
namespace BlazorSample.Pages;
[SupportedOSPlatform("browser")]
public partial class CallDotNet1
{
[JSImport("setMessage", "CallDotNet1")]
internal static partial void SetWelcomeMessage();
[JSExport]
internal static string GetMessageFromDotnet()
{
return "Olá do Blazor!";
}
}
Lo spazio dei nomi dell'app per la classe parziale precedente CallDotNet1
è BlazorSample
. Lo spazio dei nomi del componente è BlazorSample.Pages
. Se si usa il componente precedente in un'app di test locale, aggiornare lo spazio dei nomi dell'app in modo che corrisponda all'app. Ad esempio, lo spazio dei nomi del componente è ContosoApp.Pages
se lo spazio dei nomi dell'app è ContosoApp
. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.
Nell'esempio seguente viene importata una JS funzione denominata setMessage
da un file collocato JS .
Il metodo setMessage
:
- Chiama
globalThis.getDotnetRuntime(0)
per esporre l'istanza di runtime .NET di WebAssembly per chiamare i metodi .NET esportati. - Ottiene le esportazioni dell'assembly dell'app JS . Il nome dell'assembly dell'app nell'esempio seguente è
BlazorSample
. - Chiama il
BlazorSample.Pages.CallDotNet1.GetMessageFromDotnet
metodo dalle esportazioni (exports
). Il valore restituito, ovvero il messaggio di benvenuto, viene assegnato alCallDotNet1
testo del<span>
componente. Lo spazio dei nomi dell'app èBlazorSample
e loCallDotNet1
spazio dei nomi del componente èBlazorSample.Pages
.
CallDotNet1.razor.js
:
export async function setMessage() {
const { getAssemblyExports } = await globalThis.getDotnetRuntime(0);
var exports = await getAssemblyExports("BlazorSample.dll");
document.getElementById("result").innerText =
exports.BlazorSample.Pages.CallDotNet1.GetMessageFromDotnet();
}
Nota
La chiamata getAssemblyExports
a per ottenere le esportazioni può verificarsi in un inizializzatore JavaScript per la disponibilità nell'app.
Chiamate di importazione di più moduli
Dopo il caricamento di un JS modulo, le funzioni del modulo sono disponibili per i componenti e le classi dell'app JS , purché l'app sia in esecuzione nella finestra o nella scheda del browser senza ricaricare manualmente l'app. JSHost.ImportAsync può essere chiamato più volte nello stesso modulo senza una riduzione significativa delle prestazioni quando:
- L'utente visita un componente che chiama JSHost.ImportAsync per importare un modulo, si allontana dal componente e quindi torna al componente in cui JSHost.ImportAsync viene chiamato di nuovo per la stessa importazione del modulo.
- Lo stesso modulo viene usato da componenti diversi e caricato da JSHost.ImportAsync in ognuno dei componenti.
Uso di un singolo modulo JavaScript tra componenti
Prima di seguire le indicazioni riportate in questa sezione, leggere le sezioni Chiamare JavaScript da .NET e Chiamare .NET da JavaScript di questo articolo, che forniscono indicazioni generali sull'interoperabilità/[JSImport]
[JSExport]
.
L'esempio in questa sezione illustra come usare l'interoperabilità JS da un modulo condiviso JS in un'app lato client. Le linee guida contenute in questa sezione non sono applicabili alle Razor librerie di classi (RCL).
Vengono usati i componenti, le classi, i metodi C# e JS le funzioni seguenti:
Interop
classe (Interop.cs
): configura l'interoperabilità di importazione ed esportazione JS con gli[JSImport]
attributi e[JSExport]
per un modulo denominatoInterop
.GetWelcomeMessage
: metodo .NET che chiama la funzione importatagetMessage
JS .SetWelcomeMessage
: metodo .NET che chiama la funzione importatasetMessage
JS .GetMessageFromDotnet
: metodo C# esportato che restituisce una stringa di messaggio di benvenuto quando viene chiamato da JS.
wwwroot/js/interop.js
file: contiene le JS funzioni.getMessage
: restituisce un messaggio di benvenuto quando viene chiamato dal codice C# in un componente.setMessage
: chiama ilGetMessageFromDotnet
metodo C# e assegna il messaggio di benvenuto restituito a un elemento DOM<span>
.
Program.cs
chiama JSHost.ImportAsync per caricare il modulo dawwwroot/js/interop.js
.CallJavaScript2
component (CallJavaScript2.razor
): chiamaGetWelcomeMessage
e visualizza il messaggio di benvenuto restituito nell'interfaccia utente del componente.CallDotNet2
component (CallDotNet2.razor
): chiamaSetWelcomeMessage
.
Interop.cs
:
using System.Runtime.InteropServices.JavaScript;
using System.Runtime.Versioning;
namespace BlazorSample.JavaScriptInterop;
[SupportedOSPlatform("browser")]
public partial class Interop
{
[JSImport("getMessage", "Interop")]
internal static partial string GetWelcomeMessage();
[JSImport("setMessage", "Interop")]
internal static partial void SetWelcomeMessage();
[JSExport]
internal static string GetMessageFromDotnet()
{
return "Olá do Blazor!";
}
}
Nell'esempio precedente lo spazio dei nomi dell'app è BlazorSample
e lo spazio dei nomi completo per le classi di interoperabilità C# è BlazorSample.JavaScriptInterop
.
wwwroot/js/interop.js
:
export function getMessage() {
return 'Olá do Blazor!';
}
export async function setMessage() {
const { getAssemblyExports } = await globalThis.getDotnetRuntime(0);
var exports = await getAssemblyExports("BlazorSample.dll");
document.getElementById("result").innerText =
exports.BlazorSample.JavaScriptInterop.Interop.GetMessageFromDotnet();
}
Rendere disponibile lo System.Runtime.InteropServices.JavaScript spazio dei nomi nella parte superiore del Program.cs
file:
using System.Runtime.InteropServices.JavaScript;
Caricare il modulo in Program.cs
prima WebAssemblyHost.RunAsync della chiamata:
if (OperatingSystem.IsBrowser())
{
await JSHost.ImportAsync("Interop", "../js/interop.js");
}
CallJavaScript2.razor
:
@page "/call-javascript-2"
@rendermode InteractiveWebAssembly
@using BlazorSample.JavaScriptInterop
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call JS Example 2)
</h1>
@(message is not null ? message : string.Empty)
@code {
private string? message;
protected override void OnInitialized()
{
message = Interop.GetWelcomeMessage();
}
}
@page "/call-javascript-2"
@using BlazorSample.JavaScriptInterop
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call JS Example 2)
</h1>
@(message is not null ? message : string.Empty)
@code {
private string? message;
protected override void OnInitialized()
{
message = Interop.GetWelcomeMessage();
}
}
CallDotNet2.razor
:
@page "/call-dotnet-2"
@rendermode InteractiveWebAssembly
@using BlazorSample.JavaScriptInterop
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call .NET Example 2)
</h1>
<p>
<span id="result">.NET method not executed</span>
</p>
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
Interop.SetWelcomeMessage();
}
}
}
@page "/call-dotnet-2"
@using BlazorSample.JavaScriptInterop
<h1>
JS <code>[JSImport]</code>/<code>[JSExport]</code> Interop
(Call .NET Example 2)
</h1>
<p>
<span id="result">.NET method not executed</span>
</p>
@code {
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
Interop.SetWelcomeMessage();
}
}
}
Importante
Nell'esempio di questa sezione viene JS usata l'interoperabilità per modificare un elemento DOM esclusivamente a scopo dimostrativo dopo il rendering del componente in OnAfterRender
. In genere, è consigliabile modificare il DOM solo con JS quando l'oggetto non interagisce con Blazor. L'approccio illustrato in questa sezione è simile ai casi in cui una libreria di terze parti JS viene usata in un Razor componente, in cui il componente interagisce con la JS libreria tramite JS interoperabilità, la libreria di terze parti JS interagisce con parte del DOM e Blazor non è coinvolta direttamente con gli aggiornamenti DOM a tale parte del DOM. Per altre informazioni, vedere ASP.NET Core JavaScript interoperabilità (interoperabilità).For more information, see ASP.NET Core Blazor JavaScript interoperability (JS interop).
Risorse aggiuntive
- Documentazione dell'API
- Eseguire .NET da JavaScript
dotnet/runtime
Nel repository GitHub:
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per