Como criar seu primeiro aplicativo BlazorBuild your first Blazor app

Por Daniel Roth e Luke LathamBy Daniel Roth and Luke Latham

Importante

Webassembly mais incrivelmente em visualizaçãoBlazor WebAssembly in preview

Há suporte para o servidor mais incrivelmente no ASP.NET Core 3,0.Blazor Server is supported in ASP.NET Core 3.0. Webassembly mais incrivelmente está em versão prévia.Blazor WebAssembly is in preview.

Este tutorial mostra como criar e modificar um aplicativo Blazor.This tutorial shows you how to build and modify a Blazor app.

Siga as orientações no artigo Introdução ao ASP.NET Core mais incrivelmente para criar um projeto Blazor para este tutorial.Follow the guidance in the Introdução ao ASP.NET Core mais incrivelmente article to create a Blazor project for this tutorial. Nomeie o projeto como ToDoList.Name the project ToDoList.

Componentes do buildBuild components

  1. Navegue até cada uma das três páginas do aplicativo na pasta Pages: Início, Contador e Buscar dados.Browse to each of the app's three pages in the Pages folder: Home, Counter, and Fetch data. Essas páginas são implementadas pelos arquivos de componente Razor Index.razor, Counter.razor e FetchData.razor.These pages are implemented by the Razor component files Index.razor, Counter.razor, and FetchData.razor.

  2. Na página Contador, selecione o botão Clique aqui para incrementar o contador sem uma atualização de página.On the Counter page, select the Click me button to increment the counter without a page refresh. A incrementação de um contador em uma página da Web normalmente exige JavaScript, mas o Blazor fornece uma abordagem melhor usando C#.Incrementing a counter in a webpage normally requires writing JavaScript, but Blazor provides a better approach using C#.

  3. Examine a implementação do componente Counter no arquivo Counter.razor.Examine the implementation of the Counter component in the Counter.razor file.

    Pages/Counter.razor:Pages/Counter.razor:

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount++;
        }
    }
    

    A interface do usuário do componente Counter é definida usando HTML.The UI of the Counter component is defined using HTML. A lógica de renderização dinâmica (por exemplo, loops, condicionais, expressões) é adicionada usando uma sintaxe de C# inserida chamada Razor.Dynamic rendering logic (for example, loops, conditionals, expressions) is added using an embedded C# syntax called Razor. A marcação HTML e a lógica de renderização de C# são convertidas em uma classe de componente no momento da compilação.The HTML markup and C# rendering logic are converted into a component class at build time. O nome da classe .NET gerada corresponde ao nome do arquivo.The name of the generated .NET class matches the file name.

    Os membros da classe de componente são definidos em um bloco @code.Members of the component class are defined in an @code block. No bloco @code, o estado do componente (propriedades, campos) e os métodos são especificados para manipulação de eventos ou para definição de outra lógica de componente.In the @code block, component state (properties, fields) and methods are specified for event handling or for defining other component logic. Assim, esses membros são usados como parte da lógica de renderização do componente e para manipulação de eventos.These members are then used as part of the component's rendering logic and for handling events.

    Quando o botão Clique aqui botão é selecionado:When the Click me button is selected:

    • O manipulador onclick registrado do componente Counter é chamado (o método IncrementCount).The Counter component's registered onclick handler is called (the IncrementCount method).
    • O componente Counter regenera sua árvore de renderização.The Counter component regenerates its render tree.
    • A nova árvore de renderização é comparada à anterior.The new render tree is compared to the previous one.
    • Apenas as modificações ao DOM (Modelo de Objeto do Documento) são aplicadas.Only modifications to the Document Object Model (DOM) are applied. A contagem exibida é atualizada.The displayed count is updated.
  4. Modifique a lógica de C# do componente Counter para que o incremento da contagem seja por dois em vez de um.Modify the C# logic of the Counter component to make the count increment by two instead of one.

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        private void IncrementCount()
        {
            currentCount += 2;
        }
    }
    
  5. Recompile e execute o aplicativo para ver as alterações.Rebuild and run the app to see the changes. Selecione o botão Clique aqui.Select the Click me button. O contador incrementa em dois.The counter increments by two.

Usar componentesUse components

Inclua um componente em outro componente usando uma sintaxe HTML.Include a component in another component using an HTML syntax.

  1. Adicione o componente Counter no componente Index do aplicativo adicionando um elemento <Counter /> ao componente Index (Index.razor).Add the Counter component to the app's Index component by adding a <Counter /> element to the Index component (Index.razor).

    Se você estiver usando Webassembly mais experiente para essa experiência, um SurveyPrompt componente será usado Index pelo componente.If you're using Blazor WebAssembly for this experience, a SurveyPrompt component is used by the Index component. Substitua o elemento <SurveyPrompt> pelo elemento <Counter />.Replace the <SurveyPrompt> element with a <Counter /> element. Se você estiver usando um aplicativo de servidor mais experiente para essa experiência, adicione <Counter /> o elemento Index ao componente:If you're using a Blazor Server app for this experience, add the <Counter /> element to the Index component:

    Pages/Index.razor:Pages/Index.razor:

    @page "/"
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <Counter />
    
  2. Recompile e execute o aplicativo.Rebuild and run the app. O componente Index tem seu próprio contador.The Index component has its own counter.

Parâmetros do componenteComponent parameters

Componentes também podem ter parâmetros.Components can also have parameters. Os parâmetros de componente são definidos usando propriedades públicas na classe de componente [Parameter] com o atributo.Component parameters are defined using public properties on the component class with the [Parameter] attribute. Use atributos para especificar argumentos para um componente na marcação.Use attributes to specify arguments for a component in markup.

  1. Atualizar o código C# do componente @code:Update the component's @code C# code:

    • Adicione uma propriedade IncrementAmount pública com o [Parameter] atributo.Add a public IncrementAmount property with the [Parameter] attribute.
    • Altere o método IncrementCount para usar o IncrementAmount ao aumentar o valor de currentCount.Change the IncrementCount method to use the IncrementAmount when increasing the value of currentCount.

    Pages/Counter.razor:Pages/Counter.razor:

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
    
    @code {
        private int currentCount = 0;
    
        [Parameter]
        public int IncrementAmount { get; set; } = 1;
    
        private void IncrementCount()
        {
            currentCount += IncrementAmount;
        }
    }
    
  1. Especifique um parâmetro IncrementAmount no elemento <Counter> do componente Index usando um atributo.Specify an IncrementAmount parameter in the Index component's <Counter> element using an attribute. Defina o valor para incrementar o contador em 10.Set the value to increment the counter by ten.

    Pages/Index.razor:Pages/Index.razor:

    @page "/"
    
    <h1>Hello, world!</h1>
    
    Welcome to your new app.
    
    <Counter IncrementAmount="10" />
    
  2. Recarregue o componente Index.Reload the Index component. O contador é incrementado em dez sempre que o botão Clique aqui é selecionado.The counter increments by ten each time the Click me button is selected. O contador no componente Counter continua a incrementar em um.The counter in the Counter component continues to increment by one.

Rotear para componentesRoute to components

A diretiva @page no início do arquivo Counter.razor especifica que esse componente Counter é um ponto de extremidade de roteamento.The @page directive at the top of the Counter.razor file specifies that the Counter component is a routing endpoint. O componente Counter manipula solicitações enviadas para /counter.The Counter component handles requests sent to /counter. Sem a diretiva @page, o componente não lidará com as solicitações roteadas, mas ele ainda poderá ser usado por outros componentes.Without the @page directive, a component doesn't handle routed requests, but the component can still be used by other components.

Injeção de dependênciaDependency injection

Se estiver trabalhando com um aplicativo de servidor mais incrivelmente WeatherForecastService , o serviço será registrado como um Startup.ConfigureServices singleton no.If working with a Blazor Server app, the WeatherForecastService service is registered as a singleton in Startup.ConfigureServices. Uma instância do serviço está disponível em todo o aplicativo por meio de injeção de dependência (di):An instance of the service is available throughout the app via dependency injection (DI):

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();
    services.AddServerSideBlazor();
    services.AddSingleton<WeatherForecastService>();
}

A @inject diretiva é usada para injetar a instância WeatherForecastService do serviço no FetchData componente.The @inject directive is used to inject the instance of the WeatherForecastService service into the FetchData component.

Pages/FetchData.razor:Pages/FetchData.razor:

@page "/fetchdata"
@using ToDoList.App.Services
@inject WeatherForecastService ForecastService

O componente FetchData usa o serviço injetado, como ForecastService, para recuperar uma matriz de objetos WeatherForecast:The FetchData component uses the injected service, as ForecastService, to retrieve an array of WeatherForecast objects:

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }
}

Se estiver trabalhando com um aplicativo Webassembly de mais HttpClient alto, o é injetado para obter dados de previsão do tempo do arquivo Weather. JSON na pasta wwwroot/Sample-data .If working with a Blazor WebAssembly app, HttpClient is injected to obtain weather forecast data from the weather.json file in the wwwroot/sample-data folder.

Pages/FetchData.razor:Pages/FetchData.razor:

@inject HttpClient Http

...

protected override async Task OnInitializedAsync()
{
    forecasts = 
        await Http.GetJsonAsync<WeatherForecast[]>("sample-data/weather.json");
}

Um loop @foreach é usado para renderizar cada uma das instâncias de previsão do tempo como uma linha na tabela de dados do tempo:A @foreach loop is used to render each forecast instance as a row in the table of weather data:

<table class="table">
    <thead>
        <tr>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var forecast in forecasts)
        {
            <tr>
                <td>@forecast.Date.ToShortDateString()</td>
                <td>@forecast.TemperatureC</td>
                <td>@forecast.TemperatureF</td>
                <td>@forecast.Summary</td>
            </tr>
        }
    </tbody>
</table>

Criar uma lista de tarefas pendentesBuild a todo list

Adicione um novo componente ao aplicativo que implemente uma lista de tarefas pendentes simples.Add a new component to the app that implements a simple todo list.

  1. Adicione um arquivo vazio chamado Todo.razor ao aplicativo na pasta Pages:Add an empty file named Todo.razor to the app in the Pages folder:

  2. Forneça a marcação inicial do componente:Provide the initial markup for the component:

    @page "/todo"
    
    <h1>Todo</h1>
    
  3. Adicione o componente Todo à barra de navegação.Add the Todo component to the navigation bar.

    O componente NavMenu (Shared/NavMenu.razor) é usado no layout do aplicativo.The NavMenu component (Shared/NavMenu.razor) is used in the app's layout. Layouts são componentes que permitem que você evite a duplicação de conteúdo no aplicativo.Layouts are components that allow you to avoid duplication of content in the app.

    Adicione um elemento <NavLink> para o componente Todo adicionando a seguinte marcação de item da lista abaixo dos itens existentes no arquivo Shared/NavMenu.razor:Add a <NavLink> element for the Todo component by adding the following list item markup below the existing list items in the Shared/NavMenu.razor file:

    <li class="nav-item px-3">
        <NavLink class="nav-link" href="todo">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Todo
        </NavLink>
    </li>
    
  4. Recompile e execute o aplicativo.Rebuild and run the app. Visite a nova página de Tarefas Pendentes para confirmar se o link para o componente Todo está funcionando.Visit the new Todo page to confirm that the link to the Todo component works.

  5. Adicione um arquivo TodoItem.cs à raiz do projeto para manter uma classe que representará um item de tarefa pendente.Add a TodoItem.cs file to the root of the project to hold a class that represents a todo item. Use o seguinte código C# para a classe TodoItem:Use the following C# code for the TodoItem class:

    public class TodoItem
    {
        public string Title { get; set; }
        public bool IsDone { get; set; }
    }
    
  6. Retorne para o componente Todo (Pages/Todo.razor):Return to the Todo component (Pages/Todo.razor):

    • Adicione um campo para os itens de tarefas pendentes em um bloco @code.Add a field for the todo items in an @code block. O componente Todo usa esse campo para manter o estado da lista de tarefas pendentes.The Todo component uses this field to maintain the state of the todo list.
    • Adicione marcação da lista não ordenada e um loop foreach para renderizar cada item de tarefa pendente como um item de lista (<li>).Add unordered list markup and a foreach loop to render each todo item as a list item (<li>).
    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
    }
    
  7. O aplicativo requer elementos de interface do usuário para adicionar itens de tarefas à lista.The app requires UI elements for adding todo items to the list. Adicione uma entrada de texto (<input>) e um botão (<button>) abaixo da lista não ordenada (<ul>...</ul>):Add a text input (<input>) and a button (<button>) below the unordered list (<ul>...</ul>):

    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    <input placeholder="Something todo" />
    <button>Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
    }
    
  8. Recompile e execute o aplicativo.Rebuild and run the app. Nada acontece quando o botão Adicionar tarefas pendentes é selecionado porque nenhum manipulador de eventos está conectado ao botão.When the Add todo button is selected, nothing happens because an event handler isn't wired up to the button.

  9. Adicione um método AddTodo ao componente Todo e registre-o para seleções de botão usando o atributo @onclick.Add an AddTodo method to the Todo component and register it for button selections using the @onclick attribute. O método C# AddTodo é chamado quando o botão é selecionado:The AddTodo C# method is called when the button is selected:

    <input placeholder="Something todo" />
    <button @onclick="AddTodo">Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
    
        private void AddTodo()
        {
            // Todo: Add the todo
        }
    }
    
  10. Para obter o título do novo item de tarefas pendentes, adicione um campo de cadeia de caracteres newTodo na parte superior de @code, bloqueie e associe-o ao valor da próxima entrada de texto usando o atributo bind no elemento <input>:To get the title of the new todo item, add a newTodo string field at the top of the @code block and bind it to the value of the text input using the bind attribute in the <input> element:

    private IList<TodoItem> todos = new List<TodoItem>();
    private string newTodo;
    
    <input placeholder="Something todo" @bind="newTodo" />
    
  11. Atualize o método AddTodo para adicionar o TodoItem com o título especificado à lista.Update the AddTodo method to add the TodoItem with the specified title to the list. Limpe o valor da entrada de texto configurando newTodo para uma cadeia de caracteres vazia:Clear the value of the text input by setting newTodo to an empty string:

    @page "/todo"
    
    <h1>Todo</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>@todo.Title</li>
        }
    </ul>
    
    <input placeholder="Something todo" @bind="newTodo" />
    <button @onclick="AddTodo">Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
        private string newTodo;
    
        private void AddTodo()
        {
            if (!string.IsNullOrWhiteSpace(newTodo))
            {
                todos.Add(new TodoItem { Title = newTodo });
                newTodo = string.Empty;
            }
        }
    }
    
  12. Recompile e execute o aplicativo.Rebuild and run the app. Adicione alguns itens de tarefas à lista de tarefas para testar o novo código.Add some todo items to the todo list to test the new code.

  13. O texto do título de cada item de tarefa pode ser editável, e uma caixa de seleção pode ajudar o usuário a manter o controle dos itens concluídos.The title text for each todo item can be made editable, and a check box can help the user keep track of completed items. Adicione uma entrada de caixa de seleção para cada item de tarefa pendente e associe seu valor à propriedade IsDone.Add a check box input for each todo item and bind its value to the IsDone property. Altere @todo.Title para um elemento <input> associado a @todo.Title:Change @todo.Title to an <input> element bound to @todo.Title:

    <ul>
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind="todo.IsDone" />
                <input @bind="todo.Title" />
            </li>
        }
    </ul>
    
  14. Para verificar se esses valores estão associados, atualize o cabeçalho <h1> para mostrar uma contagem do número de itens de tarefa pendente que não estão concluídos (IsDone é false).To verify that these values are bound, update the <h1> header to show a count of the number of todo items that aren't complete (IsDone is false).

    <h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
    
  15. O componente Todo concluído (Pages/Todo.razor):The completed Todo component (Pages/Todo.razor):

    @page "/todo"
    
    <h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>
    
    <ul>
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind="todo.IsDone" />
                <input @bind="todo.Title" />
            </li>
        }
    </ul>
    
    <input placeholder="Something todo" @bind="newTodo" />
    <button @onclick="AddTodo">Add todo</button>
    
    @code {
        private IList<TodoItem> todos = new List<TodoItem>();
        private string newTodo;
    
        private void AddTodo()
        {
            if (!string.IsNullOrWhiteSpace(newTodo))
            {
                todos.Add(new TodoItem { Title = newTodo });
                newTodo = string.Empty;
            }
        }
    }
    
  16. Recompile e execute o aplicativo.Rebuild and run the app. Adicione itens de tarefa pendente para testar o novo código.Add todo items to test the new code.