Blazor Essentials: Seu Guia Passo a Passo

Introdução ao Blazor
Blazor está se tornando uma das estruturas mais populares e amplamente utilizadas para o desenvolvimento de aplicativos da Web modernos. Em essência, ele representa uma estrutura da Web .NET que permite criar SPA (aplicativo de página única) do lado do cliente usando C#, sintaxe Razor e HTML. Há muitos motivos para começar a usá-lo em seu próximo projeto, pois ele oferece muitos benefícios, como arquitetura baseada em componentes, elementos de interface do usuário compartilháveis entre páginas, interoperabilidade com JavaScript e muito mais.
Para entender melhor como Blazor e Ignite UI for Blazor funcionam, criamos este Guia Rápido Blazor Essencial com exemplos, snippets de código e casos de uso.
Blazor Essencial
O que é Blazor?
Blazor é uma estrutura da Web .NET que nos permite criar aplicativos do lado do cliente usando C#, sintaxe Razor e HTML. Ele nos permite criar um aplicativo de página única (SPA) rico e moderno, usando C#, e executá-lo no navegador de nossa escolha.

O nome "Blazor" vem da capacidade do framework de executar C# e Razor no navegador. A combinação de "navegador" e "Razor" nos dá o nome "Blazor".
Por que devemos usar Blazor?
- Blazor nos permite criar uma interface do usuário rica e interativa usando C# - uma linguagem moderna e rica em recursos.
- Podemos reutilizar a lógica do aplicativo compartilhando-a com o cliente e o servidor. Isso nos permite ter uma experiência de desenvolvimento .NET full-stack.
- Podemos usar APIs e ferramentas .NET existentes para criar aplicativos Web avançados.
- Blazor tem suporte no Visual Studio e no Visual Studio Code. Isso fornece uma ótima experiência de desenvolvimento .NET em várias plataformas, incluindo Linux, Windows e Mac.
- Compatível com todos os navegadores modernos, incluindo navegadores móveis.
- É uma estrutura de código aberto com grande suporte da comunidade.
- Fácil de hospedar o aplicativo usando o IIS, o serviço de aplicativo do Azure e o Docker.
Características do Blazor
- Arquitetura baseada em componentes: Blazor nos fornece uma arquitetura baseada em componentes para criar uma interface do usuário rica e combinável
- Layouts: Podemos compartilhar elementos comuns da interface do usuário (por exemplo, menus) entre páginas usando o recurso de layouts.
- Interoperabilidade JavaScript: Isso nos permite invocar um método C# do JavaScript e podemos chamar uma função JavaScript ou API do código C#.
- Roteamento: Podemos redirecionar a solicitação do cliente de um componente para outro com a ajuda do roteamento.
- Formulários e validação: Podemos criar formulários interativos para lidar com as entradas do usuário e aplicar técnicas de validação para lidar com quaisquer erros no formulário.
- Gestão do Estado: Podemos persistir o estado do aplicativo para o usuário na memória do navegador. No entanto, se o usuário reabrir o navegador ou recarregar a página, o estado do usuário mantido na memória do navegador será perdido.
- Globalização e localização: Um aplicativo Blazor pode ser disponibilizado para usuários em várias culturas e idiomas. Isso nos permite estender o alcance de nosso aplicativo para um público mundial.
- Aplicativos Web progressivos: Podemos criar um aplicativo Blazor como um aplicativo da Web progressivo. Isso permitirá que o aplicativo Blazor funcione offline e carregue instantaneamente, independentemente da velocidade da rede do usuário.
- Carregamento lento: O carregamento lento nos permite atrasar o carregamento de alguns assemblies de aplicativos até que eles sejam necessários. Isso melhorará o desempenho de inicialização do aplicativo.
- Depuração: Podemos depurar os Blazor aplicativos WebAssembly em navegadores baseados em Chromium, como Microsoft Edge e Google Chrome. E também, o suporte à depuração no Firefox está se tornando disponível (atualmente, está em fase de visualização). Também podemos depurar o aplicativo no Visual Studio e no Visual Studio Code IDE.
Blazor Modelo de Hospedagem
O modelo de componente do Blazor é responsável por calcular as alterações da interface do usuário. No entanto, podemos usar renderizadores diferentes para controlar como a interface do usuário é exibida e atualizada. Esses renderizadores são conhecidos como modelos de hospedagem.
Blazor suporta dois modelos de hospedagem
- Blazor WebAssembly
- Blazor Servidor
Modelo de execução do servidor Blazor
O que é Blazor Server?
O modelo de hospedagem do servidor Blazor permite que o aplicativo Blazor seja executado no servidor sobre o runtime completo do .NET.
Como funciona o Blazor Server?
O modelo de execução do servidor Blazor é mostrado na imagem abaixo:

Quando o usuário carrega o aplicativo, um pequeno arquivo JavaScript (blazor.server.js) é baixado no navegador que estabelece uma conexão bidirecional do SignalR em tempo real com o servidor.
Qualquer interação do usuário com o aplicativo é transmitida de volta ao servidor pela conexão do SignalR usando o protocolo WebSocket por padrão. O servidor processará a solicitação do cliente. Depois que o servidor é concluído, todas as atualizações da interface do usuário são transmitidas de volta ao cliente e aplicadas ao DOM.
O servidor mantém um estado para cada cliente conectado. Esse estado é conhecido como circuito.
Um circuito é criado quando iniciamos o aplicativo no navegador. Cada instância do aplicativo no navegador cria um novo circuito no servidor. Isso significa que, se você abrir o aplicativo em duas guias diferentes do mesmo navegador, dois circuitos serão criados no servidor.
Quando o aplicativo é fechado, fechando o navegador ou navegando para uma URL externa, o circuito e os recursos associados são liberados imediatamente.
Vantagens de usar o Blazor Server
O servidor Blazor nos oferece as seguintes vantagens.
- O tamanho do download do aplicativo é significativamente menor em comparação com o aplicativo Blazor WebAssembly. Isso ajuda a carregar o aplicativo mais rapidamente.
- Um aplicativo de servidor Blazor aproveita ao máximo os recursos do servidor, como APIs compatíveis com .NET.
- Como o aplicativo é executado no servidor, podemos aproveitar ao máximo as ferramentas existentes do .NET, como depuração.
- A base de código do aplicativo não é compartilhada com os clientes.
Quando usar o Blazor Server?
O aplicativo de servidor Blazor é preferencial nos seguintes cenários:
- Quando você deseja que o aplicativo seja carregado rapidamente.
- Quando você deseja que o aplicativo acesse o servidor e os recursos de rede.
- Como cada interação do usuário envolve um salto de rede, há uma alta latência observada nos aplicativos de servidor Blazor. Portanto, vá com o servidor Blazor onde a alta latência não é um problema.
- Como todo o trabalho pesado é feito pelo servidor, Blazor servidor é preferido quando os recursos do cliente são limitados.
- Blazor servidor é adequado para navegadores que não suportam WebAssembly.
Blazor WebAssembly
O que é Blazor WebAssembly?
O modelo de hospedagem Blazor WebAssembly (WASM) permite que o aplicativo Blazor seja executado no lado do cliente no navegador em um runtime do .NET baseado em WebAssembly. É o principal modelo de hospedagem para Blazor.
Como funciona Blazor WebAssembly?
O modelo de execução WASM Blazor é mostrado na imagem abaixo:

Quando o usuário carrega o aplicativo, um pequeno arquivo JavaScript (blazor.webassembly.js) é baixado no navegador.
Esse arquivo lida com as duas operações a seguir:
- Ele baixa o runtime do .NET junto com o aplicativo Blazor e suas dependências para o navegador.
- Ele inicializa o runtime do .NET para executar o aplicativo.
A execução do aplicativo acontece diretamente no thread da interface do usuário do navegador. As atualizações da interface do usuário e a manipulação de eventos também ocorrem no mesmo processo.
Um servidor Web ou qualquer outro serviço que possa fornecer conteúdo estático aos clientes pode ser usado para implantar os ativos do aplicativo como arquivos estáticos.
Tipos de Blazor aplicativo WebAssembly
Existem dois tipos de Blazor aplicativo WASM:
- Autônomo: Quando o aplicativo WebAssembly Blazor é criado para implantação sem um aplicativo ASP.NET Core de back-end para servir seus arquivos, o aplicativo é chamado de aplicativo WASM Blazor autônomo.
- Hospedado: Quando o aplicativo é criado para implantação com um aplicativo de back-end para servir seus arquivos, o aplicativo é chamado de aplicativo WASM Blazor hospedado. Um aplicativo hospedado fornece uma experiência de desenvolvimento da Web de pilha completa com o .NET. Ele nos permite compartilhar código entre os aplicativos cliente e servidor e oferecer suporte à pré-renderização e integração com MVC e Razor Pages.
Vantagens de usar Blazor WebAssembly
O Blazor WebAssembly nos oferece as seguintes vantagens:
- Não há dependência do lado do servidor depois que o aplicativo é baixado para o cliente. Isso garante que o aplicativo permaneça funcional mesmo se o servidor ficar offline.
- O cliente fará o trabalho pesado. Portanto, há menos carga no servidor.
- O aplicativo aproveita ao máximo os recursos do cliente.
- Como um servidor não é necessário para hospedar o aplicativo, há suporte para cenários de implantação sem servidor.
Quando usar Blazor WebAssembly?
O aplicativo WASM Blazor é preferencial nos seguintes cenários:
- Quando queremos que o aplicativo aproveite os recursos do cliente.
- Quando o aplicativo for necessário para ser executado offline se o cliente não conseguir se conectar à Internet.
- Quando queremos hospedar o aplicativo como um site estático.
Blazor Híbrido
O que é Blazor Híbrido?
Blazor Hybrid nos permite criar aplicativos clientes nativos usando .NET, HTML e CSS. Podemos usar as estruturas de aplicativo nativas do .NET existentes, como .NET MAUI, WPF e Windows Forms, para criar um aplicativo híbrido Blazor.
Como funciona Blazor Híbrido?
Um aplicativo híbrido Blazor executa os componentes da navalha nativamente no dispositivo. Os componentes Blazor são renderizados em um controle de exibição da Web inserido por meio de um canal de interoperabilidade local. Os componentes são executados diretamente no aplicativo nativo e não no navegador. Portanto, o WebAssembly não está envolvido em um aplicativo híbrido.
Um aplicativo híbrido pode acessar os recursos da plataforma nativa por meio de APIs do .NET. Por ser um aplicativo nativo, um aplicativo híbrido Blazor pode suportar funcionalidades que não estão disponíveis apenas com a plataforma web. Também podemos compartilhar e reutilizar os componentes de navalha existentes de um servidor Blazor ou de um aplicativo WASM Blazor com um aplicativo híbrido Blazor.
Vantagens de usar Blazor Hybrid
- Ele nos permite reutilizar componentes existentes do servidor Blazor e Blazor aplicativo WASM. Isso permite o compartilhamento e a reutilização de código em plataformas móveis, de desktop e da Web.
- O aplicativo pode aproveitar os recursos nativos do dispositivo.
Quando usar Blazor Hybrid?
O aplicativo Blazor Híbrido é preferencial nos seguintes cenários:
- Quando queremos criar um aplicativo nativo usando APIs .NET.
- Quando queremos aproveitar os recursos nativos do cliente.
- Quando o aplicativo é necessário para ser executado offline.
- Quando queremos descarregar o processamento de dados do aplicativo para o cliente
Blazor Componentes
Quais são Blazor componentes?
Um componente Blazor é definido como parte da interface do usuário, como a barra de navegação, botões, formulário, etc. Blazor componentes são criados como arquivos de componente Razor com a extensão ".razor".
Os componentes são reutilizáveis e podem ser compartilhados entre vários projetos. Um componente Blazor também é conhecido como componente Razor.
Razor é uma sintaxe de marcação para combinar código HTML e C#.
O nome de um componente Blazor deve começar com um caractere maiúsculo.

por exemplo, o nome LoginForm.razor é um nome de componente válido. Considerando que o nome loginForm.razor é um nome de componente inválido.
Veja o exemplo de código do componente mostrado abaixo:
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Contador</h1>
<p role="status" >Contagem atual: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Clique em mim</button>
@code {
private int currentCount = 0;
privado void IncrementCount()
{
currentCount++;
}
}
A diretiva @page é usada para especificar a rota para o componente. A diretiva @code é usada para especificar o código C# para o componente. O método IncrementCount será invocado no evento de clique do botão.
Também podemos usar várias, mas distintas, diretivas @page para um único componente. Não podemos definir a mesma rota para dois componentes diferentes. Isso resultará em um erro de tempo de execução.
Classe base do componente
Podemos criar uma classe base para o componente para separar a lógica HTML e C#. A classe base deve derivar da classe ComponentBase. Podemos usar a diretiva @inherits para herdar uma classe base em um componente.
Criamos uma classe base Welcome.razor.cs conforme mostrado abaixo:
usando Microsoft.AspNetCore.Components;
namespace BlazorTutorial.Client.Pages;
public class WelcomeBase : ComponentBase { public string WelcomeMessage { get; set; } = "Bem-vindo ao Blazor tutorial."; }
Criamos um componente razor Welcome.razor como mostrado abaixo:
@page "/bem-vindo"
@inherits Base de boas-vindas
<h1>@WelcomeMessage</h1>
Estamos usando a diretiva @inherits para herdar a classe base.
Parâmetros do componente
Os parâmetros do componente são usados para passar dados do componente pai para o filho.
Vamos entender isso com a ajuda de um exemplo.
Crie um componente Child.razor conforme mostrado abaixo:
<h3>Componente filho</h3>
<p>A soma do número é: @(num1 + num2)</p>
@code {
[Parâmetro]
public int num1 { get; set; }
[Parâmetro]
public int num2 { get; set; }
}
Os parâmetros do componente são anotados com o atributo [Parameter]. Este componente aceitará dois parâmetros do tipo inteiro e exibirá a soma de ambos os números.
Crie outro componente Parent.razor conforme mostrado abaixo:
@page "/pai"
<h3>Componente pai</h3>
<Criança num1="5" num2="10"><Criança>
Invocamos o componente Child dentro do componente Parent e passamos os dois parâmetros para ele.
Também podemos atribuir a propriedade C# ao valor do parâmetro usando o símbolo "@".
Veja o exemplo mostrado abaixo:
@page "/pai"
<h3>Componente pai</h3>
<Criança num1="@number1" num2="@number2"><Criança>
@code {
int número1 = 5;
int number2 = 10;
}
Um parâmetro pode ser marcado como obrigatório usando o atributo [EditorRequired].
Veja o exemplo mostrado abaixo:
<h3>Componente filho</h3>
<p>A soma do número é: @(num1 + num2)<p>
@code {
[Parâmetro]
[Editor necessário]
public int num1 { get; set; }
[Parâmetro]
[Editor necessário]
public int num2 { get; set; }
}
Devemos usar o atributo [Parameter] ao usar o atributo [EditorRequired].
Se não fornecermos os parâmetros necessários ao invocar o componente, ele lançará um aviso em tempo de compilação.
Também podemos fornecer valores padrão para os parâmetros do componente.
Veja o exemplo mostrado abaixo:
@page "/bem-vindo"
<h1>Mensagem de boas-vindas</h1>
@code {
[Parâmetro]
string pública WelcomeMessage { get; set; } = "Bem-vindo";
}
Razor ciclo de vida do componente
Razor componentes passam por uma série de eventos de ciclo de vida desde sua criação até serem removidos. Possui métodos síncronos e assíncronos. A estrutura Blazor nos permite substituir métodos de ciclo de vida para executar operações adicionais em componentes.
SetParametersAsync
Esse método será chamado antes que os parâmetros sejam definidos. Ele definirá os parâmetros fornecidos pelo componente pai ou pela rota do componente. Devemos chamar a base. SetParametersAsync() para definir o valor dos parâmetros do componente. Caso contrário, precisamos escrever nosso código personalizado para manipular os parâmetros.
OnInitialized
Esse método será chamado antes que os parâmetros sejam definidos. Ele será invocado quando o componente estiver pronto para iniciar após receber os parâmetros iniciais de seu pai.
A versão assíncrona é chamada OnInitializedAsync. Substitua OnInitializedAsync se quiser executar uma operação assíncrona e quiser que o componente seja atualizado quando essa operação for concluída.
OnParametersSet
Este método será chamado depois que os parâmetros forem definidos. Ele será chamado quando o componente tiver recebido parâmetros de seu pai e os valores de entrada tiverem sido atribuídos às propriedades. Este método será executado toda vez que os parâmetros forem atualizados. A versão assíncrona é chamada OnParametersSetAsync.
OnAfterRender
Este método será chamado depois que um componente terminar de renderizar, ou seja, o HTML já estiver exibido. Esse método pode ser usado para executar quaisquer etapas extras necessárias para a inicialização do componente, como ativar quaisquer bibliotecas JavaScript de terceiros que usem os elementos DOM renderizados. Esse método é executado sempre que o componente é renderizado. A versão assíncrona é conhecida como OnAfterRenderAsync.
StateHasChanged
Esse método notificará o componente de que seu estado foi alterado e, em seguida, renderizará novamente o componente. Durante um EventCallback, esse método será chamado automaticamente para renderizar novamente o componente Pai.
Invocar esse método nos permitirá renderizar o componente a qualquer momento. No entanto, muitas chamadas para StateHasChanged podem adicionar custos de renderização desnecessários ao aplicativo.
Vamos entender isso com a ajuda de um exemplo.
Criamos uma classe base Lifecycle.razor.cs conforme mostrado abaixo:
usando Microsoft.AspNetCore.Components;
namespace BlazorTutorial.Client.Pages;
classe pública LifecycleBase: ComponentBase { public override async Task SetParametersAsync(ParameterView parameters){ Console.WriteLine("SetParametersAsync-start"); Aguarde a base. SetParametersAsync(parâmetros); Console.WriteLine("SetParametersAsync-end"); }
protected override void OnInitialized() { Console.WriteLine("OnInitialized-start"); base. OnInitialized(); Console.WriteLine("OnInitialized-end"); }
protected override async Task OnInitializedAsync() { Console.WriteLine("OnInitializedAsync-start"); Aguarde a base. OnInitializedAsync(); Console.WriteLine("OnInitializedAsync-end"); }
substituição protegida void OnParametersSet() { Console.WriteLine("OnParametersSet-start"); base. OnParametersSet(); Console.WriteLine("OnParametersSet-end"); }
protected override async Task OnParametersSetAsync() {Console.WriteLine("OnParametersSetAsync-start"); Aguarde a base. OnParametersSetAsync(); Console.WriteLine("OnParametersSetAsync-end"); }
protected override void OnAfterRender(bool firstRender) { Console.WriteLine("OnAfterRender({0})-start", firstRender); base. OnAfterRender(firstRender); Console.WriteLine("OnAfterRender({0})-end", firstRender); }
protected override async Task OnAfterRenderAsync(bool firstRender) { Console.WriteLine("OnAfterRenderAsync({0})-start", firstRender); Aguarde a base. OnAfterRenderAsync(firstRender); Console.WriteLine("OnAfterRenderAsync({0})-end", firstRender); } }
Criamos um componente de barbear Lifecycle.razor conforme mostrado abaixo:
@page "/lifecycle"
@inherits Base de boas-vindas
<h1> Blazor exemplo de ciclo de vida do componente</h1>
Quando executamos o aplicativo e navegamos até o componente do ciclo de vida, podemos ver a saída no console do navegador, conforme mostrado abaixo:

Esta saída mostra a sequência de execução dos métodos de ciclo de vida de um componente Razor.
Blazor Valores e parâmetros em cascata
Valores e parâmetros em cascata nos permitem passar dados de um componente para todos os seus componentes descendentes. Um componente pode fornecer um valor em cascata usando o componente <CascadingValue>.
Para utilizar os valores em cascata fornecidos pelo componente pai, um componente filho pode declarar parâmetros em cascata usando o atributo [CascadingParameter].
Os valores em cascata são associados a parâmetros em cascata por tipo de dados. Se quisermos colocar em cascata vários valores do mesmo tipo, podemos fornecer um nome exclusivo para cada atributo [CascadingParameter].
Vamos entender isso com a ajuda de um exemplo.
Crie um componente Child.razor conforme mostrado abaixo:
<h3>Componente filho</h3>
<p>A soma do número é: @(num1 + num2)</p>
@code {
[CascadingParameter(Nome = "FirstNumber")]
public int num1 { get; set; }
[CascadingParameter(Nome = "SecondNumber")]
public int num2 { get; set; }
}
Crie um componente Parent.razor conforme mostrado abaixo:
@page "/pai"
<h3>Componente pai</h3>
<Valor em cascata Value="@number1" Name="FirstNumber" >
<Valor do Valor em Cascata="@number2" Nome="SegundoNúmero" >
<Criança></Criança>
</CascadingValue>
</CascadingValue>
@code {
int número1 = 5;
int number2 = 10;
}
Chamamos o componente Child e passamos os valores em cascata. O componente filho vinculará os valores de parâmetro usando a propriedade Name.
Passar dados em uma hierarquia de componentes
Podemos usar os parâmetros em cascata para passar dados pela hierarquia de componentes.
Vamos entender isso com a ajuda de um exemplo.
Crie um componente GrandChild.razor conforme mostrado abaixo:
<h3>Componente Filho</h3>
<p>O produto do número é: @(num1 * num2)</p>
@code {
[CascadingParameter(Nome = "FirstNumber")]
public int num1 { get; set; }
[CascadingParameter(Nome = "SecondNumber")]
public int num2 { get; set; }
}
Crie um componente Child.razor conforme mostrado abaixo:
<h3>Componente filho</h3>
<p>A soma do número é: @(num1 + num2)</p>
<Neto></Neto>
@code {
[Parâmetro]
public int num1 { get; set; }
[Parâmetro]
public int num2 { get; set; }
}
@page "/pai"
<h3>Componente pai</h3>
<Valor em cascata Value="10" Name="FirstNumber" >
<Valor em cascata Value="5" Name="SecondNumber" >
<Criança></Criança>
</CascadingValue>
</CascadingValue>
@code {
int número1 = 5;
int number2 = 10;
}
Passamos os valores em cascata do componente Pai para o componente Neto. Observe que o nome dos parâmetros em cascata é o mesmo nos componentes Child e GrandChild.
Após a execução, você pode ver uma saída conforme mostrado abaixo:

Blazor vinculação de dados
Vinculação de dados unidirecional
Ele nos permite vincular o valor de uma propriedade a elementos HTML DOM, mas não vice-versa. Para vincular uma propriedade ou um campo a uma tag HTML, precisamos passar o nome da propriedade, prefixado com o símbolo @.
Veja o exemplo mostrado abaixo:
@page "/databinding"
<h3>Vinculação de dados unidirecional</h3>
<p>@SampleText</p>
@code {
string SampleText = "Este é um texto de exemplo que descreve a vinculação de dados unidirecional";
}
O campo C# SampleText é associado ao HTML DOM usando o símbolo @.
Ligação de dados bidirecional
Ele nos permite vincular o valor de uma propriedade ou campo a elementos HTML DOM e vice-versa. Podemos obter a vinculação de dados bidirecional usando o atributo @bind.
Podemos associar uma propriedade C# em eventos DOM usando o atributo @bind:event="{EVENT}" nos elementos HTML, em que {EVENT} é um espaço reservado para os eventos DOM.
Veja o exemplo mostrado abaixo:
@page "/databinding"
<h3>Ligação de dados bidirecional</h3>
<div>
<span>Digite seu nome: </span>
<input type="text" @bind="Nome" @bind:event="oninput" />
</div>
<br/>
<p>Seu nome é: @Name</p>
@code {
string Nome { get; set; }
}
O valor do campo de entrada está associado à propriedade Name. A vinculação de dados ocorrerá quando o evento oninput do campo de entrada for acionado, ou seja, quando o valor da caixa de texto for alterado.
NOTE:
A associação de atributo diferencia maiúsculas de minúsculas. Isso significa @bind, @bind:event é válido, enquanto @Bind, @Bind:EVENT e outras sintaxes usando caracteres maiúsculos são inválidas.
Vincular várias opções usando o elemento <selecionar>
Podemos associar os valores de uma seleção múltipla a uma propriedade C# do tipo matriz.
Veja o exemplo mostrado abaixo:
@page "/databinding"
<p>
<rótulo>
Selecione um ou mais dias:
<select @onchange="SelectedDaysChanged" vários >
<valor da opção ="segunda-feira">segunda-feira</opção>
<option value="terça-feira">terça-feira</opção>
<valor da opção="quarta-feira">quarta-feira</opção>
<option value="quinta-feira">quinta-feira</opção>
<valor da opção="sexta-feira">sexta-feira</opção>
</selecionar>
</rótulo>
</p>
<p>
Dias selecionados: @string. Join(", ", SelectedDays)
</p>
@code {
string pública[] SelectedDays { get; set; } = new string[] { };
void SelectedDaysChanged(ChangeEventArgs e)
{
if (e.Value não é nulo) {
SelectedDays = (string[])e.Value;
}
}
}
Os valores selecionados são associados a uma matriz de cadeias de caracteres usando o evento @onchange do elemento <select>.
Associar a uma cadeia de caracteres formatada
A vinculação de dados funciona com uma cadeia de caracteres formatada usando a sintaxe @bind:format="{FORMAT STRING}"
A associação de dados formatada tem suporte para os seguintes tipos de .NET:
- System.DateTime
- System.DateTimeOffset
Veja o exemplo mostrado abaixo:
@page "/databinding"
<h3>String formatada</h3>
<div>
<span>A data da amostra é: </span>
<input @bind="SampleDate" @bind:format="dd-MM-aaaa" />
</div>
@code {
DataHora AmostraData { get; set; } = new DataHora(2023, 1, 14);
}
A data será exibida no formato especificado usando o atributo @bind:format.
Podemos especificar um formato de associação personalizado usando os acessadores get e set.
Veja o exemplo mostrado abaixo:
@page "/databinding"
<input @bind="SalaryValue" />
<h3>String formatada</h3>
<p>
<code>decimalValue</code>: @salary
</p>
@code {
salário decimal = 123456;
string ValorSalário {
Receba = > salário. ToString("0,000");
conjunto {
if (Decimal.TryParse(valor, out var number)) {
salário = Math.Round(número, 3);
}
}
}
}
A propriedade de cadeia de caracteres SalaryValue é associada até três casas decimais ao elemento input.
Associação com parâmetros de componente
Podemos vincular a propriedade de um componente filho a uma propriedade em seu componente pai. Como a associação de dados ocorre em vários níveis, esse cenário é conhecido como associação encadeada.
Podemos usar a sintaxe @bind-{PROPERTY}, em que {PROPERTY} é um espaço reservado para a propriedade a ser vinculada. Devemos fornecer um manipulador de eventos e um valor para dar suporte à atualização da propriedade no pai do componente filho.
Vamos entender isso com a ajuda de um exemplo.
Crie um componente Child.razor conforme mostrado abaixo:
<h3>Componente filho</h3>
<p>Mensagem Filho: @Message</p>
<button @onclick="UpdateMessageFromChild">Atualizar mensagem da criança</button>
@code {
[Parâmetro]
string pública Mensagem { get; set; }
[Parâmetro]
public EventCallback <string> MessageChanged { get; set; }
Tarefa assíncrona privada UpdateMessageFromChild() {
await MessageChanged.InvokeAsync("Mensagem do componente filho");
}
}
Declaramos um parâmetro de componente do tipo string e um EventCallback do mesmo tipo que o parâmetro de componente.
O nome do EventCallback deve seguir a sintaxe {PARAMETER NAME}Changed, em que {PARAMETER NAME} é um espaço reservado para o nome do parâmetro do componente. O uso de qualquer outro formato de nomenclatura resultará em um erro de tempo de execução.
No exemplo mostrado acima, o parâmetro component é chamado Message e o EventCallback é nomeado como MessageChanged.
Crie um componente Parent.razor conforme mostrado abaixo:
@page "/pai"
<h3>Componente pai</h3>
<Child @bind-Message="MesssageFromParent"></Child>
<button @onclick="UpdateMessageFromChild">Atualizar mensagem da criança</button>
@code {
string MesssageFromParent = "Mensagem do componente pai";
}
A propriedade C# MesssageFromParent está associada ao parâmetro Message do componente Child. O parâmetro Message do componente filho é vinculável porque tem um evento MessageChanged complementar do mesmo tipo que o parâmetro Message.
Após a execução, você pode ver uma saída conforme mostrado abaixo:

Assim que você clicar no botão, a mensagem será atualizada conforme a imagem abaixo:

Blazor manipulação de eventos
Adicione um atributo HTML com o nome @on{EVENT} e tenha um valor de tipo delegado. O valor desse atributo é tratado como um manipulador de eventos pelo componente Blazor.
Alguns dos manipuladores de eventos suportados pelo Blazor são @onclick, @onchange, @onselect, @onfocus, @onkeyup etc.
Exemplo:
<button @onclick="ButtonClicked">Clique em mim</button>
@code {
void ButtonClicked() {
Console.WriteLine("botão clicado");
}
}
O método ButtonClicked será invocado quando clicarmos no botão.
Manipulação de eventos assíncronos
Veja o exemplo mostrado abaixo:
<button @onclick="ButtonClicked">Clique em mim</button>
@code {
Tarefa assíncrona ButtonClicked() {
aguarde Task.Delay(1000);
Console.WriteLine("botão clicado");
}
}
O método ButtonClicked será invocado de forma assíncrona quando o botão for clicado.
Usando argumentos de evento
Veja o exemplo mostrado abaixo:
<select class="form-control col-md-4" @onchange="SelectGender" />
<option value="">-- Selecione Gênero --</option>
<option value="Masculino">Masculino</opção>
<option value="Famale">Famale</option>
</selecionar>
@code {
string protegida Gender { get; set; }
protegido void SelectGender(ChangeEventArgs e) {
Gênero = e.Value.ToString();
}
}
Associamos o método SelectGender ao evento onchange do elemento select.
A especificação de um argumento de evento na definição do método de evento é opcional. É obrigatório somente quando o argumento de evento é usado no método.
Usar expressões Lambda para manipulação de eventos
Podemos usar uma expressão lambda para criar uma função anônima para o atributo event.
Veja o exemplo mostrado abaixo:
@for (int i = 1; i < 4; i++) {
int textboxNumber = i;
<p>
<input> @onfocus="@(() => FocusTextbox(textboxNumber))" />
</p>
}
@code {
string protegida Gender { get; set; }
protegido void FocusTextbox(int textboxNumber) {
Console.WriteLine($"Você selecionou o número da caixa de texto {textboxNumber}");
}
}
Criamos três controles de caixa de texto usando um loop for. Usamos uma expressão lambda para invocar o método FocusTextbox no evento onfocus de cada caixa de texto.
EventCallback
EventCallback pode ser usado para expor eventos em vários componentes. Isso ajuda a chamar o método de um componente pai quando ocorre um evento em um componente filho.
Podemos digitar fortemente um EventCallback especificando um parâmetro de evento usando a sintaxe EventCallback<TValue>.
Por exemplo, EventCallback<MouseEventArgs>
Vamos entender EventCallback com a ajuda de um exemplo.
Crie um componente Child.razor conforme mostrado abaixo:
<h3>Componente filho</h3>
<classe do botão="btn btn-primary" @onclick="ChildClick">
Chamar método do componente pai
</botão>
@code {
[Parâmetro]
public EventCallback ChildClick { get; set; }
}
Crie outro componente Parent.razor conforme mostrado abaixo:
<h3>Componente pai</h3>
<Child ChildClick="ChildClickHandler"> </Child>
<p><forte> @message </forte></p>
@code {
string mensagem { get; set; }
void ChildClickHandler() {
message = "Ocorreu um evento filho";
}
}
Criamos um parâmetro EventCallback no componente filho. O manipulador de eventos onclick do botão é configurado para receber um delegado EventCallback do ParentComponent.
O ParentComponent define o EventCallback do componente filho, ChildClick como seu método ChildClickHandler.
Quando clicamos no botão no componente Filho, ele invoca o método ChildClickHandler do Componente Pai. A mensagem da propriedade string é atualizada e exibida no ParentComponent.
Impedir ações padrão
Podemos usar o atributo de diretiva @on{DOM EVENT}:p reventDefault para evitar a ação padrão de um evento. Esse atributo aceita um valor booleano como argumento. Se não especificarmos nenhum argumento, o valor padrão de true será considerado.
Veja o exemplo mostrado abaixo:
<valor de entrada = "@name" @onkeydown = "KeyDownHandler" @onkeydown: preventDefault / >
@code {
nome da string privada { get; set; }
private void KeyDownHandler(KeyboardEventArgs e) {
faça algo
}
}
O atributo booleano pode ser vinculado a uma propriedade e, portanto, podemos controlar a propagação do evento com base no requisito do usuário.
Veja o exemplo mostrado abaixo:
<input @onkeydown="KeyDownHandler" @onkeydown:preventDefault="shouldPreventDefault" />
@code {
private bool shouldPreventDefault = true;
}
Parar a propagação de eventos
Às vezes, os elementos HTML propagam eventos para seus elementos pai.
Blazor nos permite usar o atributo de diretiva @on{DOM EVENT}:stopPropagation para interromper a propagação de eventos. Esse atributo aceita um valor booleano como argumento. Se não especificarmos nenhum argumento, o valor padrão de true será considerado.
Veja o exemplo mostrado abaixo:
<botão @onclick:stopPropagation>Click</button>
O atributo booleano pode ser vinculado a uma propriedade e, portanto, podemos controlar a propagação do evento com base no requisito do usuário.
<botão @onclick:stopPropagation="shouldStopPropagation">Clique</button>
@code {
private bool shouldStopPropagation = true;
}
Roteamento e navegação
O componente Router, usado no arquivo App.razor, permite o roteamento para os componentes em um aplicativo Blazor.
Quando criamos um aplicativo Blazor, o arquivo App.razor conterá o código conforme mostrado abaixo.
<Router AppAssembly="@typeof(App). > de montagem
<Contexto encontrado = "routeData" >
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" / >
<FocusOnNavigate RouteData="@routeData" Selector="h1" / >
</Encontrado>
<Não encontrado>
<PageTitle>NotFound</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert"> Desculpe, não há nada neste endereço.</p>
</LayoutView>
</Não encontrado>
</Roteador>
O componente Roteador é usado para fornecer dados de rota correspondentes ao estado de navegação atual. O componente FocusOnNavigate é usado para definir o foco de um elemento correspondente a um seletor CSS quando o usuário navega de um componente para outro. Isso nos permite criar um mecanismo de roteamento acessível que é compatível com leitores de tela.
A propriedade NotFound é usada para exibir conteúdo personalizado quando nenhum dado é encontrado na rota solicitada.
Podemos usar a diretiva @page para definir a rota para um componente Razor. Também podemos usar diretivas @page múltiplas, mas distintas, para um único componente.
Veja o exemplo mostrado abaixo:
@page "/route1"
@page "/home/route1"
<h1>Este componente pode ser acessado por meio de várias rotas.</h1>
Não podemos definir a mesma rota para dois componentes diferentes. Isso resultará em um erro de tempo de execução.
Parâmetros de rota
Podemos definir parâmetros de rota que podem ser usados para preencher parâmetros de componentes com o mesmo nome. Uma rota pode ter vários parâmetros.
Veja o exemplo mostrado abaixo:
@page "/home/{Nome}/{Mensagem}"
<h1>Olá @Name</h1>
<h3>@Message</h3>
@code {
[Parâmetro]
string pública Nome { get; set; }
[Parâmetro]
string pública Mensagem { get; set; }
}
A propriedade do parâmetro de rota do componente deve ser definida como pública. O uso de qualquer outro modificador de acesso resultará em um erro de tempo de compilação.
Os nomes dos parâmetros de rota não diferenciam maiúsculas de minúsculas, o que significa que podemos usar os parâmetros de rota conforme mostrado abaixo:
@page "/home/{nome}/{mensagem}"
<h1>Olá @NAME</h1>
<h3>@MESSAGE</h3>
@code {
[Parâmetro]
string pública NOME { get; set; }
[Parâmetro]
string pública MENSAGEM { get; set; }
}
Blazor também oferece suporte a parâmetros de rota opcionais. Para marcar um parâmetro de rota como opcional, sufixe-o com o ? símbolo.
Veja o exemplo mostrado abaixo:
@page "/home/{nome}/{mensagem?}"
<h1>Olá @Name</h1>
<h3>@Message</h3>
@code {
[Parâmetro]
string pública Nome { get; set; }
[Parâmetro]
string pública Mensagem { get; set; }
}
Podemos ter mais de um parâmetro opcional.
A rota a seguir é válida.
@page "/home/{nome}/{mensagem?}/{texto?}"
Os parâmetros não opcionais não podem aparecer após os parâmetros opcionais. Se você adicionar qualquer parâmetro não opcional após um parâmetro opcional, receberá um erro de tempo de execução.
A rota a seguir é inválida.
@page "/home/{nome?}/{mensagem}"
Restrições de rota
Podemos usar as restrições de rota para impor a correspondência de tipo na rota.
Veja o exemplo mostrado abaixo:
@page "/home/{name}/{userID:int}/{isAdmin:bool}"
<h1>Olá @Name</h1>
<h3>ID do usuário: @userID</h3>
<h3>isAdmin: @isAdmin</h3>
@code {
[Parâmetro]
string pública Nome { get; set; }
[Parâmetro]
public int userID { get; set; }
[Parâmetro]
public Boolean isAdmin { get; set; }
}
A rota para este componente corresponderá se os seguintes critérios forem atendidos:
- A rota deve ter um valor para o parâmetro name.
- A rota deve ter um valor para o parâmetro userID e deve ser do tipo int.
- A rota deve ter um valor para o parâmetro isAdmin e deve ser do tipo bool.
Um exemplo de rota para corresponder a esse padrão pode ser – "/home/John/1234/true"
Também podemos usar restrições de rota com parâmetros opcionais.
por exemplo:
@page "/home/{name}/{userID:int}/{isAdmin:bool?}"
NavigationManager
Podemos usar a classe NavigationManager para lidar com a navegação por meio do código C#. Essa classe fornece um método NavigateTo, que aceita a rota do componente como um parâmetro e redireciona o usuário de um componente para outro.
Vamos entender isso com a ajuda de um exemplo.
Criamos uma classe base Routing.razor.cs conforme mostrado abaixo:
usando Microsoft.AspNetCore.Components;
namespace BlazorWasmDemo.Client.Pages;
public class RoutingBase : ComponentBase { [Inject] public NavigationManager NavigationManager { get; set; }
[Parâmetro] public string Nome { get; set; }
protegido void NavigateAway() { NavigationManager.NavigateTo("parent/1234"); } }
Adicionaremos o código a seguir no componente Routing.razor.
@page "/home/{nome}"
@inherits RoutingBase
<h1>Olá @Name</h1>
<button @onclick="NavigateAway" >Navigate away</button>
Invocaremos o método NavigateAway com o clique de um botão. Ele redirecionará o usuário para a rota "/parent/1234".
O método NavigateTo aceita um parâmetro booliano opcional, forceLoad. Se passarmos o valor verdadeiro para este parâmetro, o navegador recarregará a nova página do servidor.
Parâmetros de rota catch-all
Um parâmetro de rota catch-all pode ser usado para lidar com várias rotas quando os parâmetros de roteamento não são definidos explicitamente.
Veja o componente de exemplo mostrado abaixo:
@page "/home/{*routeParams}"
@code {
[Parâmetro]
string pública? RouteParams { get; set; }
}
Para este componente, as seguintes rotas são válidas:
- /home/João
- /início/123
- /home/John/123/345/EUA/true
Um parâmetro de rota catch-all deve seguir os seguintes critérios:
- Ele deve ter um parâmetro de componente correspondente com o mesmo nome. O nome não diferencia maiúsculas de minúsculas.
- Deve ser um tipo de cadeia de caracteres. Não podemos usar restrições de rota neles.
- Ele deve estar presente no final do URL.
Componente NavLink
Podemos usar o componente NavLink no lugar do atributo <a> em HTML ao criar links de navegação. Ele alterna uma classe CSS ativa, com base em se a URL atual corresponde à propriedade href. Isso ajuda o usuário a entender quais páginas estão ativas entre todos os links de navegação disponíveis.
por exemplo:
<NavLink class="nav-link" href="" Match="NavLinkMatch.All" >
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
O atributo Match do componente NavLink pode ter dois valores possíveis:
- NavLinkMatch.All: NavLink deve estar ativo somente se corresponder a toda a URL atual
- NavLinkMatch.Prefix: NavLink deve estar ativo somente se corresponder a qualquer prefixo da URL atual. Esse é o valor padrão.
Cadeias de caracteres de consulta
Podemos usar o atributo [SupplyParameterFromQuery] junto com o atributo [Parameter] para especificar que o parâmetro do componente pode ser fornecido por meio de uma cadeia de caracteres de consulta da rota.
@page "/filme"
<p>@Name</p>
<p>@Genre</p>
@code {
[Parâmetro]
[SupplyParameterFromQuery]
string pública? Nome { get; set; }
[Parâmetro]
[SupplyParameterFromQuery]
string pública? Gênero { get; set; }
}
Uma rota válida para este componente pode ser "/movie?name=avatar&genre=science%20fiction" Podemos especificar o nome do parâmetro de consulta usando a propriedade Name.
por exemplo:
[Parâmetro]
[SupplyParameterFromQuery(Name="Categoria")]
string pública? Gênero { get; set; }
Uma rota válida, neste caso, será "/movie?name=avatar&category =science%20fiction"
Um parâmetro de consulta para o componente suporta os seguintes tipos de dados:
- bool
- Data e hora
- decimal
- dobro
- flutuar
- Guid
- int
- Longas
- corda
Podemos usar o método GetUriWithQueryParameter da classe NavigationManager para adicionar, atualizar ou excluir um ou mais parâmetros de consulta da URL atual.
A sintaxe desse método é GetUriWithQueryParameter("{NAME}", {VALUE}), em que {NAME} é um espaço reservado para o nome do parâmetro de consulta e {VALUE} é um espaço reservado para o valor do parâmetro de consulta. O método retornará um valor de cadeia de caracteres.
Se o parâmetro de consulta já existir no URI atual, esse método atualizará o valor. Se o parâmetro de consulta não existir no URI atual, esse método adicionará o novo parâmetro com o valor especificado.
por exemplo:
@page "/filme"
@inject Navegação do NavigationManager
<p>@Name</p>
<p>@Genre</p>
<button @onclick="UpdateCurrentURI">Atualizar URI</button>
<p>NewURI: @NewURI</p>
<button @onclick="NavigateToNewURI">Ir para o novo URI</button>
@code {
string NewURI { get; set; }
[Parâmetro]
[SupplyParameterFromQuery]
string pública? Nome { get; set; }
[Parâmetro]
[SupplyParameterFromQuery(Nome = "Categoria")]
string pública? Gênero { get; set; }
void UpdateCurrentURI() {
NewURI = Navigation.GetUriWithQueryParameter("nome", "Top Gun");
}
void NavigateToNewURI() {
Navigation.NavigateTo(NewURI);
}
}
O valor do parâmetro de consulta, "nome" será atualizado quando clicarmos no botão.
Se quisermos acrescentar um novo parâmetro de consulta ao URI, podemos atualizar o código conforme mostrado abaixo:
NewURI = Navigation.GetUriWithQueryParameter("idioma", "Inglês");
Se quisermos remover um parâmetro de consulta existente do URI, podemos definir o valor como nulo, conforme mostrado abaixo:
NewURI = Navigation.GetUriWithQueryParameter("nome", (cadeia de caracteres?)nulo);
Podemos usar o método GetUriWithQueryParameters para adicionar, atualizar e remover vários parâmetros de um URI simultaneamente.
Veja o exemplo mostrado abaixo:
NewURI = Navigation.GetUriWithQueryParameters(new Dictionary<string, object?>
{
["nome"] = "Top Gun",
["categoria"] = "Ação",
["idioma"] = "inglês",
});
Isso atualizará os parâmetros de consulta existentes, nome e categoria e adicionará um novo parâmetro de consulta, idioma com o valor definido como inglês.
Blazor layouts
Um layout é um componente Blazor que contém os recursos de interface do usuário que são comuns em vários componentes, como o menu de navegação, cabeçalho, rodapé etc. O layout padrão do aplicativo é definido no componente Roteador dentro do arquivo App.razor.
Podemos usar layouts apenas para os componentes de Razor roteáveis com a diretiva @page. O layout padrão do aplicativo é definido no componente Roteador dentro do arquivo App.razor.
Podemos usar a diretiva @layout para especificar o layout de um componente roteável com a diretiva @page. Especificar o layout diretamente em um componente substitui o layout padrão do aplicativo definido no componente Roteador.
Veja o exemplo mostrado abaixo:
@layout CustomLayout
@page "/layout-demo"
<h1>Demonstração de layout personalizado.</h1>
Blazor suporta o aninhamento de layouts. Um componente pode se referir a um layout, que por sua vez se referirá a outro layout. Isso pode ajudar a criar uma estrutura de menu de vários níveis.
Criar um componente de layout personalizado
Para que um componente atue como um componente de layout, ele deve atender aos dois critérios a seguir:
- Ele deve ser herdado da classe LayoutComponentBase. Essa classe define uma propriedade Body, que é usada para renderizar o conteúdo dentro do layout.
- Ele deve definir um local para especificar onde o conteúdo do corpo deve ser renderizado. Isso é feito usando Razor sintaxe @Body.
Veja o exemplo mostrado abaixo:
@inherits LayoutComponentBase
<cabeçalho>
<h1>Bem-vindo ao Blazor tutorial</h1>
</cabeçalho>
@Body
<rodapé>
<h1>Todos os direitos reservados</h1>
</rodapé>
Injeção de dependência
A injeção de dependência (DI) é um padrão de design de software que nos ajuda a alcançar a Inversão de Controle (IoC) entre classes e suas dependências.
Podemos injetar os serviços registrados na estrutura diretamente nos componentes Blazor. Os serviços personalizados devem ser registrados no aplicativo Blazor para disponibilizá-los via DI.
Vida útil
Blazor serviços podem ser configurados com os três tempos de vida a seguir:
- Singleton: Cria uma única instância de um serviço que é compartilhado entre todos os componentes.
- Transitório: Cria uma nova instância de um serviço sempre que um componente solicita o serviço.
- Escopo: Isso cria uma instância de serviço por solicitação da Web.
- Os aplicativos WebAssembly Blazor não dão suporte ao tempo de vida com escopo. Um serviço registrado com escopo se comporta como um serviço Singleton para aplicativos WebAssembly Blazor.
- Os aplicativos do Blazor Server dão suporte ao tempo de vida com escopo em solicitações HTTP, mas não em mensagens de conexão do SignalR entre componentes carregados no lado do cliente.
Serviços de Blazor padrão
Os serviços mostrados na tabela a seguir são usados com frequência em aplicativos Blazor.
Serviço | Blazor Vida do Wasm | Tempo de vida do servidor Blazor | Descrição |
---|---|---|---|
HttpClient | Escopo | Escopo | Fornece métodos para lidar com solicitações e respostas HTTP de uma URL de recurso. |
IJSRuntime | Singleton | Escopo | Representa uma instância de um runtime JavaScript em que as chamadas JavaScript são despachadas. |
NavigationManager | Singleton | Escopo | Fornece classes auxiliares para consultar e gerenciar a navegação de URI. |
Adicionar serviços a um aplicativo WASM Blazor
Podemos usar o arquivo Program.cs para registrar serviços personalizados para o aplicativo Blazor Wasm e o aplicativo Blazor Server.
Examine o exemplo de código do arquivo Program.cs para um aplicativo Wasm Blazor:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
Veja o exemplo de código do arquivo Program.cs para um aplicativo Blazor Server:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
var app = builder.Build();
app.UseRouting();
app.Run();
Injetar um serviço em Blazor componente
Podemos injetar um serviço em um componente usando os dois métodos a seguir:
- Usando o atributo [Inject] na classe base.
- Usando a diretiva @inject no componente.
Podemos injetar vários serviços em um único componente.
Veja o exemplo mostrado abaixo para o componente Razor:
@page "/filme"
@inject Navegação do NavigationManager
<button @onclick="NavigateToPage">Ir para a página</button>
@code {
void NavigateToPage()
{
Navigation.NavigateTo("/home");
}
}
Veja o exemplo mostrado abaixo para a classe base:
usando Microsoft.AspNetCore.Components;
namespace BlazorWasmDemo.Client.Pages
{ public class RoutingBase : ComponentBase { [Inject] public NavigationManager NavigationManager { get; set; } = default!;
[Injetar] HttpClient Http { get; set; } = padrão!;} }
Espera-se que os serviços injetados estejam disponíveis à medida que o componente é inicializado Portanto, atribuímos um literal padrão com o operador tolerante a nulos (padrão!). Se não atribuirmos um valor padrão não nulo, o compilador mostrará uma mensagem de aviso como "A propriedade não anulável deve conter um valor não nulo ao sair do construtor". Como alternativa, com o SDK do .NET versão 7 ou posterior, o modificador "required", adicionado do C#11, pode ser usado para escrever o seguinte sem recorrer ao operador tolerante a nulo.
[Injetar] public necessário NavigationManager NavigationManager { get; set; }
Use a injeção de dependência em serviços Blazor.
Podemos usar a injeção do construtor para injetar um serviço em outro serviço. O atributo [Inject] ou a diretiva @inject não está disponível para uso na classe de serviço.
Veja o exemplo mostrado abaixo:
classe pública MyCustomService
{ private readonly HttpClient _httpClient;_httpClient HttpClient somente leitura privada; public MyCustomService(HttpClient, httpClient, NavigationManager, navigationManager) { _httpClient = httpClient; _navigationManager = navigationManager; } }
Interoperabilidade JavaScript
A interoperabilidade do JavaScript, também conhecida como interoperabilidade do JavaScript, é definida como a capacidade de invocar funções JavaScript de métodos .NET e métodos .NET de funções JavaScript.
Chamar funções JavaScript de métodos .NET
Podemos usar a abstração IJSRuntime para chamar funções JavaScript do .NET.
A interface IJSRuntime fornece dois métodos:
- InvokeAsync: é usado para chamar as funções JavaScript que retornam qualquer valor ou objeto, incluindo uma promessa.
- InvokeVoidAsync: é usado para chamar as funções JavaScript que retornam void ou undefined.
Podemos adicionar o código JavaScript personalizado no wwwroot/index.html em um aplicativo WebAssembly Blazor. Podemos adicionar o código JavaScript personalizado no Pages/_Host.cshtml em um aplicativo WebAssembly Blazor.
Vamos entender isso com um exemplo.
<script>
window.getArraySum = (numberArray) => {
return numberArray.reduce((a, b) => a + b, 0);
}
</script>
A função getArraySum aceitará uma matriz como parâmetro e retornará a soma de todos os elementos da matriz.
Crie um componente JSDemoBase.razor e adicione o código a seguir à classe base JSDemoBase.razor.cs.
usando Microsoft.AspNetCore.Components;
usando Microsoft.JSInterop;
namespace BlazorWasmDemo.Client.Pages;
classe pública JSDemoBase: ComponentBase
{ [Injetar] IJSRuntime protegido JSRuntime { get; set; } = default!;
protected int sumOfArray = 0;
private int[] arrayItems = new int[] { 2, 4, 6, 8, 10 };
Tarefa assíncrona protegida GetSumOfArray(){ sumOfArray = await JSRuntime.InvokeAsync<int>("getArraySum", arrayItems); } }
Usaremos o método InvokeAsync para invocar a função JS. A função JS retornará a soma e será atribuída a uma variável inteira sumOfArray.
Esse método GetSumOfArray pode ser invocado em um clique de botão, conforme mostrado abaixo:
@page "/calljsmethod"
@inherits JSDemoBase
<button @onclick="GetSumOfArray">Obter soma da matriz</button>
<p>A soma dos elementos da matriz é: @sumOfArray</p>
Se quisermos invocar os métodos embutidos do JavaScript, podemos usar o seguinte trecho de código:
Tarefa assíncrona protegida ShowAlert()
{ await JSRuntime.InvokeVoidAsync("alerta", "Sou invocado do código .NET"); }
Tarefa assíncrona protegida ShowArrayItems()
{ await JSRuntime.InvokeVoidAsync("console.table", arrayItems); }
Invocamos a função de alerta e passamos um parâmetro de string para ela. O método ShowArrayItems invocará a função console.table do JavaScript e passará o arrayItems a ser exibido como entrada.
Capturar referências a elementos HTML
Podemos capturar as referências a elementos HTML em um componente usando o struct ElementReference. Ele é usado para representar uma referência a um elemento renderizado.
Para capturar referências a elementos HTML em um componente, precisamos adicionar um atributo @ref ao elemento HTML. Além disso, defina um campo do tipo ElementReference cujo nome corresponda ao valor do atributo @ref.
Podemos passar o ElementReference para o código JS por meio da interoperabilidade JS. O código JS receberá uma instância HTMLElement que pode ser usada para manipulação do DOM.
Vamos entender isso com um exemplo.
Adicione o seguinte código JS.
<script>
window.showValue = (elemento) => {
alert('Seu nome é :' + elemento.valor);
}
</script>
Essa função receberá a referência de um elemento HTML e exibirá o valor em uma caixa de alerta.
Podemos adicionar o código a seguir na classe base para invocar essa função.
nome ElementReference protegido;
Tarefa assíncrona protegida ShowName()
{ await JSRuntime.InvokeVoidAsync("showValue", nome); }
Podemos usar o atributo @ref em um elemento HTML para capturar a instância ElementReference, conforme mostrado no código abaixo:
<button class="btn btn-primary" @onclick="ShowName">Show Name</button>
<input type="text" @ref="name" class="form-control" placeholder="Digite seu nome" />
Chamar métodos .NET estáticos de funções JavaScript
Podemos usar as funções DotNet.invokeMethod ou DotNet.invokeMethodAsync para invocar um método .NET estático do JS.
O método .NET deve atender aos seguintes critérios:
- Deve ser declarado como público e estático.
- Ele deve ser decorado com o atributo [JSInvokable].
Podemos passar o identificador do método estático, o nome do assembly que contém o método C# e quaisquer argumentos necessários.
A sintaxe da função é - DotNet.invokeMethodAsync('{ASSEMBLY NAME}', '{.NET METHOD Name}', {ARGUMENTS});
onde
- {ASSEMBLY NAME} é um espaço reservado para o nome do assembly do aplicativo.
- {.NET METHOD Name} é um espaço reservado para o método .NET a ser invocado.
- {ARGUMENTS} é um espaço reservado para o argumento exigido pelo método .Net a ser invocado. Este é um parâmetro opcional.
Vamos entender isso com um exemplo.
Adicione o código a seguir no arquivo JSDemoBase.razor.cs.
usando Microsoft.AspNetCore.Components;
usando Microsoft.JSInterop;
namespace BlazorTutorial.Client.Pages;
classe pública JSDemoBase: ComponentBase
{ [Injetar] protegido IJSRuntime JSRuntime { get; set; } = default!;
protegido void InvokeJSMethod() { JSRuntime.InvokeVoidAsync("printMessageToConsole"); }
[JSInvokable] public static Task<string> PrintMessage() { return Task.FromResult("Sou invocado do JavaScript."); }}
O InvokeJSMethod chamará uma função JS, printMessageToConsole. O método PrintMessage tem o atributo [JSInvokable]. Esse método é declarado como público e estático. Isso permitirá que a função JS printMessageToConsole invoque o método PrintMessage.
Adicione um botão no arquivo JSDemoBase.razor, conforme mostrado abaixo:
<button @onclick="InvokeJSMethod">Invocar método .NET estático</button>
Adicione o seguinte código JS.
<script>
window.printMessageToConsole = () => {
DotNet.invokeMethodAsync(BlazorTutorial.Client', 'PrintMessage')
.then(dados => {
console.log(dados);
});
}
</script>
Criamos uma função JS, printMessageToConsole. Usaremos a função DotNet.invokeMethodAsync para invocar o método C#, PrintMessage. Passamos o nome do assembly como BlazorTutorial.Client.
Método de instância do componente de chamada
Podemos invocar o método de instância .NET de um componente Blazor usando as seguintes etapas:
- Gere uma referência de objeto .NET que pode ser passada para funções JavaScript usando DotNetObjectReference.Create.
- Faça uma chamada de método de instância para o componente usando o método invokeMethod ou invokeMethodAsync de um objeto .NET.
- Verifique se a referência de objeto .NET também está descartada quando o componente é descartado.
Vamos entender isso com um exemplo.
Adicione o seguinte código JS.
function displayMessageCallerJS(objectRef, value) {
objectRef.invokeMethodAsync('DisplayMessage', value);
}
Adicionamos uma função displayMessageCallerJS que aceitará dois parâmetros chamados objectRef e value. Essa função invocará o método DisplayMessage do objeto componente ao qual o objectRef está referenciando e passará o valor como argumento.
Adicione o seguinte código no arquivo JSDemoBase.razor.cs:
classe pública JSDemoBase: ComponentBase, IDisposable
{
private DotnetObjectReference<JSDemoBase>? refobjeto;
protected string message = "Clique no botão.";
substituição protegida void OnInitialized()
{
objectRef = DotNetObjectReference.Create(this);
}
[JSInvokable]
public void DisplayMessage(string value)
{
mensagem = valor;
StateHasChanged();
}
public void Dispose()
{
objectRef?. Dispose();
}
}
Declaramos uma variável de campo objectRef do tipo DotNetObjectReference<JSDemoBase> que representa uma referência de um objeto .NET. Dentro do método de ciclo de vida OnInitialized, estamos criando uma referência desse componente em si usando o método estático DotNetObjectReference.Create e atribuindo-o ao campo objectRef.
O método InvokeDisplayMessageCallerJS aceitará um parâmetro de cadeia de caracteres. Em seguida, esse método chamará a função JS, displayMessageCallerJS, e passará o campo de referência de objeto .NET que faz referência a esse componente como um primeiro argumento e passará o parâmetro de cadeia de caracteres como um segundo argumento.
Criamos um método de instância pública, DisplayMessage, que tem o atributo [JSInvokable] e aceitará parâmetros de cadeia de caracteres. Esse método de instância será invocado a partir da função JS displayMessageCallerJS. Atribuiremos o valor do parâmetro ao campo de mensagem e, em seguida, chamaremos o método StateHasChanged() para notificar o componente sobre a alteração de estado.
Por fim, implemente a interface IDisposable para garantir que a referência de objeto .NET que se refere ao próprio componente também seja descartada quando esse componente for descartado. Especificamente, chamamos o método Dispose da referência de objeto .NET no método Dispose desse componente.
Adicione um botão no arquivo JSDemoBase.razor, conforme mostrado abaixo:
<button @onclick="@(()=>InvokeDisplayMessageCallerJS("O botão é clicado"))">Chamar método JS</button>
<br />
<p >@message</p>
Ao clicar no botão, chamaremos o método InvokeDisplayMessageCallerJS e passaremos um valor de cadeia de caracteres como parâmetro. O valor atualizado da mensagem será exibido na tela.
Continue lendo
Preencha o formulário para continuar lendo.