Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.
Advertência
Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
As chamadas entre .NET e JavaScript exigem sobrecarga adicional porque:
- As chamadas são assíncronas.
- Parâmetros e valores de retorno são serializados em JSON para fornecer um mecanismo de conversão fácil de entender entre os tipos .NET e JavaScript.
Além disso, para aplicativos de Blazor do lado do servidor, essas chamadas são passadas pela rede.
Evite chamadas excessivamente refinadas
Uma vez que cada chamada envolve alguma sobrecarga, pode ser valioso reduzir o número de chamadas. Considere o seguinte código, que armazena uma coleção de itens no localStoragedo navegador:
private async Task StoreAllInLocalStorage(IEnumerable<TodoItem> items)
{
foreach (var item in items)
{
await JS.InvokeVoidAsync("localStorage.setItem", item.Id,
JsonSerializer.Serialize(item));
}
}
O exemplo anterior faz uma chamada de interoperabilidade de JS separada para cada item. Em vez disso, a seguinte abordagem reduz o JS interop a uma única chamada:
private async Task StoreAllInLocalStorage(IEnumerable<TodoItem> items)
{
await JS.InvokeVoidAsync("storeAllInLocalStorage", items);
}
A função JavaScript correspondente armazena toda a coleção de itens no cliente:
function storeAllInLocalStorage(items) {
items.forEach(item => {
localStorage.setItem(item.id, JSON.stringify(item));
});
}
Para aplicativos Blazor WebAssembly, rolar chamadas individuais de interoperabilidade de JS em uma única chamada geralmente só melhora significativamente o desempenho se o componente fizer um grande número de chamadas de interoperabilidade JS.
Considere o uso de chamadas síncronas
Chamar JavaScript a partir do .NET
Esta seção só se aplica a componentes do lado do cliente.
As chamadas de interop JS são assíncronas, independentemente de o código chamado ser síncrono ou assíncrono. As chamadas são assíncronas para garantir que os componentes sejam compatíveis entre os modos de renderização do lado do servidor e do lado do cliente. No servidor, todas as chamadas de interoperabilidade JS devem ser assíncronas porque são enviadas por uma conexão de rede.
Se tiveres a certeza de que o teu componente só funciona em WebAssembly, podes optar por realizar chamadas de interoperabilidade JS síncronas. Isso tem um pouco menos de sobrecarga do que fazer chamadas assíncronas e pode resultar em menos ciclos de renderização porque não há nenhum estado intermediário enquanto aguarda resultados.
Para efetuar uma chamada síncrona do .NET para JavaScript num componente do lado do cliente, é necessário converter IJSRuntime para IJSInProcessRuntime de modo a realizar a chamada interop JS.
@inject IJSRuntime JS
...
@code {
protected override void HandleSomeEvent()
{
var jsInProcess = (IJSInProcessRuntime)JS;
var value = jsInProcess.Invoke<string>("javascriptFunctionIdentifier");
}
}
Ao trabalhar com componentes do lado do cliente no .NET 5 ou posterior, pode-se usar IJSObjectReference de forma síncrona. IJSInProcessObjectReference implementa IAsyncDisposable/IDisposable e deve ser descartado para coleta de lixo para evitar um vazamento de memória, como demonstra o exemplo a seguir:
@inject IJSRuntime JS
@implements IDisposable
...
@code {
...
private IJSInProcessObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var jsInProcess = (IJSInProcessRuntime)JS;
module = await jsInProcess.Invoke<IJSInProcessObjectReference>("import",
"./scripts.js");
var value = module.Invoke<string>("javascriptFunctionIdentifier");
}
}
...
void IDisposable.Dispose()
{
if (module is not null)
{
await module.Dispose();
}
}
}
No exemplo anterior, um JSDisconnectedException não fica preso durante o descarte do módulo porque não há um circuito Blazor-SignalR em uma aplicação Blazor WebAssembly para perder. Para obter mais informações, consulte Interoperabilidade do JavaScript do ASP.NET Core Blazor (JS interop).
Chamar .NET a partir de JavaScript
Esta seção só se aplica a componentes do lado do cliente.
As chamadas de interop JS são assíncronas, independentemente de o código chamado ser síncrono ou assíncrono. As chamadas são assíncronas para garantir que os componentes sejam compatíveis entre os modos de renderização do lado do servidor e do lado do cliente. No servidor, todas as chamadas de interoperabilidade JS devem ser assíncronas porque são enviadas por uma conexão de rede.
Se tiveres a certeza de que o teu componente só funciona em WebAssembly, podes optar por realizar chamadas de interoperabilidade JS síncronas. Isso tem um pouco menos de sobrecarga do que fazer chamadas assíncronas e pode resultar em menos ciclos de renderização porque não há nenhum estado intermediário enquanto aguarda resultados.
Para fazer uma chamada síncrona de JavaScript para .NET em um componente do lado do cliente, use DotNet.invokeMethod em vez de DotNet.invokeMethodAsync.
As chamadas síncronas funcionam se:
Esta seção só se aplica a componentes do lado do cliente.
As chamadas de interop JS são assíncronas, independentemente de o código chamado ser síncrono ou assíncrono. As chamadas são assíncronas para garantir que os componentes sejam compatíveis entre os modos de renderização do lado do servidor e do lado do cliente. No servidor, todas as chamadas de interoperabilidade JS devem ser assíncronas porque são enviadas por uma conexão de rede.
Se tiveres a certeza de que o teu componente só funciona em WebAssembly, podes optar por realizar chamadas de interoperabilidade JS síncronas. Isso tem um pouco menos de sobrecarga do que fazer chamadas assíncronas e pode resultar em menos ciclos de renderização porque não há nenhum estado intermediário enquanto aguarda resultados.
Para efetuar uma chamada síncrona do .NET para JavaScript num componente do lado do cliente, é necessário converter IJSRuntime para IJSInProcessRuntime de modo a realizar a chamada interop JS.
@inject IJSRuntime JS
...
@code {
protected override void HandleSomeEvent()
{
var jsInProcess = (IJSInProcessRuntime)JS;
var value = jsInProcess.Invoke<string>("javascriptFunctionIdentifier");
}
}
Ao trabalhar com componentes do lado do cliente no .NET 5 ou posterior, pode-se usar IJSObjectReference de forma síncrona. IJSInProcessObjectReference implementa IAsyncDisposable/IDisposable e deve ser descartado para coleta de lixo para evitar um vazamento de memória, como demonstra o exemplo a seguir:
@inject IJSRuntime JS
@implements IDisposable
...
@code {
...
private IJSInProcessObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var jsInProcess = (IJSInProcessRuntime)JS;
module = await jsInProcess.Invoke<IJSInProcessObjectReference>("import",
"./scripts.js");
var value = module.Invoke<string>("javascriptFunctionIdentifier");
}
}
...
void IDisposable.Dispose()
{
if (module is not null)
{
await module.Dispose();
}
}
}
No exemplo anterior, um JSDisconnectedException não fica preso durante o descarte do módulo porque não há um circuito Blazor-SignalR em uma aplicação Blazor WebAssembly para perder. Para obter mais informações, consulte Interoperabilidade do JavaScript do ASP.NET Core Blazor (JS interop).
Considere o uso de chamadas não processadas
Esta secção aplica-se apenas a aplicações Blazor WebAssembly.
Ao executar em Blazor WebAssembly, é possível fazer chamadas não organizadas do .NET para o JavaScript. Estas são chamadas síncronas que não realizam a serialização JSON dos argumentos ou dos valores de retorno. Todos os aspetos do gerenciamento de memória e traduções entre representações .NET e JavaScript são deixados para o desenvolvedor.
Advertência
Embora o uso do IJSUnmarshalledRuntime tenha a menor sobrecarga das abordagens de interoperabilidade JS, as APIs JavaScript necessárias para interagir com essas APIs estão atualmente não documentadas e sujeitas a alterações significativas em versões futuras.
function jsInteropCall() {
return BINDING.js_to_mono_obj("Hello world");
}
@inject IJSRuntime JS
@code {
protected override void OnInitialized()
{
var unmarshalledJs = (IJSUnmarshalledRuntime)JS;
var value = unmarshalledJs.InvokeUnmarshalled<string>("jsInteropCall");
}
}
Usar a interoperabilidade JavaScript [JSImport]/[JSExport]
A interoperabilidade JavaScript [JSImport]/[JSExport] para aplicativos Blazor WebAssembly oferece melhor desempenho e estabilidade em relação à API de interoperabilidade JS em lançamentos anteriores ao ASP.NET Core no .NET 7.
Para obter mais informações, consulte Interoperabilidade JSImport/JSExport JavaScript com ASP.NET Core Blazor.