Ćwiczenie — zmienianie nawigacji w aplikacji Blazor przy użyciu dyrektywy @page
Platforma Blazor ma pomocnik stanu nawigacji, który ułatwia kodowi języka C# zarządzanie identyfikatorami URI aplikacji. Istnieje również składnik NavLink , który jest zamiennikiem <a>
elementu drop-in. Jedną z funkcji narzędzia NavLink jest dodanie aktywnej klasy do linków HTML dla menu aplikacji.
Twój zespół rozpoczął pracę nad aplikacją Blazing Pizza i zbudował składniki Blazor do reprezentowania pizzy i zamówień. Teraz aplikacja musi dodać wyewidencjonowania i inne strony związane z zamówieniem.
W tym ćwiczeniu dodasz nową stronę wyewidencjonowania, dodasz górną nawigację do aplikacji, a następnie użyjesz składnika Blazor NavLink , aby ulepszyć kod.
Klonowanie istniejącej aplikacji zespołu
Uwaga
W tym module używany jest interfejs wiersza polecenia platformy .NET i program Visual Studio Code na potrzeby programowania lokalnego. Po zakończeniu tego modułu można zastosować koncepcje przy użyciu programu Visual Studio (Windows) lub Visual Studio dla komputerów Mac (macOS). W celu dalszego programowania użyj programu Visual Studio Code dla systemów Windows, Linux i macOS.
W tym module jest używany zestaw .NET 6.0 SDK. Upewnij się, że masz zainstalowany program .NET 6.0, uruchamiając następujące polecenie w preferowanym terminalu:
dotnet --list-sdks
Pojawia się dane wyjściowe podobne do następującego:
3.1.100 [C:\program files\dotnet\sdk]
5.0.100 [C:\program files\dotnet\sdk]
6.0.100 [C:\program files\dotnet\sdk]
Upewnij się, że na liście znajduje się wersja rozpoczynająca się od 6
. Jeśli na liście nie ma żadnej listy lub nie można odnaleźć polecenia, zainstaluj najnowszy zestaw SDK platformy .NET 6.0.
Jeśli wcześniej nie utworzono aplikacji Blazor, postępuj zgodnie z instrukcjami konfiguracji platformy Blazor , aby zainstalować poprawną wersję platformy .NET i sprawdzić, czy maszyna została prawidłowo skonfigurowana. Zatrzymaj się w kroku Tworzenie aplikacji .
Otwórz Visual Studio Code.
Otwórz zintegrowany terminal z programu Visual Studio Code, wybierając pozycję Widok. Następnie w menu głównym wybierz pozycję Terminal.
W terminalu przejdź do miejsca, w którym chcesz utworzyć projekt.
Sklonuj aplikację z usługi GitHub.
git clone https://github.com/MicrosoftDocs/mslearn-blazor-navigation.git BlazingPizza
Wybierz pozycję Plik, a następnie wybierz pozycję Otwórz folder.
W oknie dialogowym Otwieranie przejdź do folderu BlazingPizza, a następnie wybierz pozycję Wybierz folder.
Program Visual Studio Code może wyświetlić monit o nierozwiązane zależności. Wybierz przycisk Przywróć.
Uruchom aplikację, aby sprawdzić, czy wszystko działa poprawnie.
W programie Visual Studio Code wybierz pozycję F5. Lub w menu Uruchom wybierz pozycję Rozpocznij debugowanie.
Skonfiguruj pizze i dodaj je do zamówienia. Wybierz pozycję Order (Kolejność > ) w dolnej części strony. Zostanie wyświetlony domyślny komunikat "Nie znaleziono 404", ponieważ nie ma jeszcze strony wyewidencjonowania.
Aby zatrzymać aplikację, wybierz pozycję Shift + F5.
Dodawanie strony wyewidencjonowania
W programie Visual Studio Code w eksploratorze plików wybierz pozycję App.razor.
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"> <Found Context="routeData"> <RouteView RouteData="@routeData" /> </Found> <NotFound> <LayoutView> <p>Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router>
Blok
<NotFound>
kodu jest tym, co klienci widzą, jeśli próbują przejść do strony, która nie istnieje.W Eksploratorze plików rozwiń węzeł Strony, kliknij prawym przyciskiem myszy folder i wybierz pozycję Nowy plik.
Nadaj nowej nazwie plik Checkout.razor. W tym pliku napisz następujący kod:
@page "/checkout" @inject OrderState OrderState @inject HttpClient HttpClient @inject NavigationManager NavigationManager <div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab"> <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> </div> <div class="main"> <div class="checkout-cols"> <div class="checkout-order-details"> <h4>Review order</h4> @foreach (var pizza in Order.Pizzas) { <p> <strong> @(pizza.Size)" @pizza.Special.Name (£@pizza.GetFormattedTotalPrice()) </strong> </p> } <p> <strong> Total price: £@Order.GetFormattedTotalPrice() </strong> </p> </div> </div> <button class="checkout-button btn btn-warning"> Place order </button> </div> @code { Order Order => OrderState.Order; }
Ta strona jest oparta na bieżącej aplikacji i korzysta ze stanu aplikacji zapisanego w programie
OrderState
. Pierwszydiv
to nowa nawigacja nagłówka aplikacji. Dodajmy go do strony indeksu.W Eksploratorze plików rozwiń węzeł Pages, a następnie wybierz pozycję index.razor.
Nad klasą
<div class="main">
top-bar
dodaj kod HTML.<div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab" > <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> </div>
Gdy jesteśmy na tej stronie, warto pokazać klientom, wyróżniając link. Zespół utworzył już klasę
active
css, więc dodajactive
do atrybutuclass
, który już zawieranav-tab
styl.<div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab active" > <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> </div>
W programie Visual Studio Code wybierz pozycję F5. Lub w menu Uruchom wybierz pozycję Rozpocznij debugowanie.
Aplikacja ma teraz ładny pasek menu u góry, który zawiera logo firmy. Dodaj pizze i postępuj zgodnie z zamówieniem na stronie wyewidencjonowania. Zobaczysz pizze wymienione i aktywny wskaźnik brakuje w menu.
Aby zatrzymać aplikację, wybierz pozycję Shift + F5.
Zezwalaj klientom na składania zamówienia
W tej chwili strona wyewidencjonowania nie zezwala klientom na składania zamówień. Logika aplikacji musi przechowywać zamówienie do wysłania do kuchni. Po wysłaniu zamówienia przekierowujmy klientów z powrotem na stronę główną.
W Eksploratorze plików rozwiń węzeł Pages i wybierz pozycję Checkout.razor.
Zmodyfikuj element przycisku za pomocą wywołania
PlaceOrder
metody .@onclick
Dodaj atrybuty idisabled
, jak pokazano:<button class="checkout-button btn btn-warning" @onclick="PlaceOrder" disabled=@isSubmitting> Place order </button>
Nie chcemy, aby klienci składali zduplikowane zamówienia, dlatego wyłączamy przycisk Składanie zamówienia do momentu przetworzenia zamówienia.
@code
W bloku dodaj ten kod wOrder Order => OrderState.Order;
kodzie.bool isSubmitting; async Task PlaceOrder() { isSubmitting = true; var response = await HttpClient.PostAsJsonAsync(NavigationManager.BaseUri + "orders", OrderState.Order); var newOrderId= await response.Content.ReadFromJsonAsync<int>(); OrderState.ResetOrder(); NavigationManager.NavigateTo("/"); }
Powyższy kod wyłącza przycisk Umieść zamówienie , publikuje kod JSON i dodaje go do pizza.db, czyści zamówienie i używa
NavigationManager
polecenia do przekierowywania klientów do strony głównej.Aby obsłużyć zamówienie, musisz dodać kod. Dodaj klasę OrderController dla tego zadania. Jeśli spojrzysz na PizzaStoreContext.cs, zobaczysz tylko obsługę bazy danych platformy entity framework dla programu
PizzaSpecials
. Naprawmy to najpierw.
Dodawanie obsługi platformy entity framework dla zamówień i pizzy
W Eksploratorze plików wybierz pozycję PizzaStoreContext.cs.
Zastąp klasę
PizzaStoreContext
następującym kodem:public class PizzaStoreContext : DbContext { public PizzaStoreContext( DbContextOptions options) : base(options) { } public DbSet<Order> Orders { get; set; } public DbSet<Pizza> Pizzas { get; set; } public DbSet<PizzaSpecial> Specials { get; set; } public DbSet<Topping> Toppings { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // Configuring a many-to-many special -> topping relationship that is friendly for serialization modelBuilder.Entity<PizzaTopping>().HasKey(pst => new { pst.PizzaId, pst.ToppingId }); modelBuilder.Entity<PizzaTopping>().HasOne<Pizza>().WithMany(ps => ps.Toppings); modelBuilder.Entity<PizzaTopping>().HasOne(pst => pst.Topping).WithMany(); } }
Ten kod dodaje obsługę platformy entity framework dla klas zamówień i pizzy aplikacji.
W programie Visual Studio Code w menu wybierz pozycję Plik>nowy plik tekstowy.
Wybierz język C#, a następnie wprowadź następujący kod:
using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace BlazingPizza; [Route("orders")] [ApiController] public class OrdersController : Controller { private readonly PizzaStoreContext _db; public OrdersController(PizzaStoreContext db) { _db = db; } [HttpGet] public async Task<ActionResult<List<OrderWithStatus>>> GetOrders() { var orders = await _db.Orders .Include(o => o.Pizzas).ThenInclude(p => p.Special) .Include(o => o.Pizzas).ThenInclude(p => p.Toppings).ThenInclude(t => t.Topping) .OrderByDescending(o => o.CreatedTime) .ToListAsync(); return orders.Select(o => OrderWithStatus.FromOrder(o)).ToList(); } [HttpPost] public async Task<ActionResult<int>> PlaceOrder(Order order) { order.CreatedTime = DateTime.Now; // Enforce existence of Pizza.SpecialId and Topping.ToppingId // in the database - prevent the submitter from making up // new specials and toppings foreach (var pizza in order.Pizzas) { pizza.SpecialId = pizza.Special.Id; pizza.Special = null; } _db.Orders.Attach(order); await _db.SaveChangesAsync(); return order.OrderId; } }
Powyższy kod umożliwia naszej aplikacji pobranie wszystkich bieżących zamówień i umieszczenie zamówienia. Atrybut
[Route("orders")]
Blazor umożliwia tej klasie obsługę przychodzących żądań HTTP dla /orders i /orders/{orderId}.Zapisz zmiany za pomocą Ctrl+S.
W przypadku nazwy pliku użyj OrderController.cs. Upewnij się, że plik został zapisany w tym samym katalogu co OrderState.cs.
W Eksploratorze plików wybierz pozycję OrderState.cs.
W dolnej części klasy w metodzie
RemoveConfiguredPizza
zmodyfikujResetOrder()
, aby zresetować kolejność:public void ResetOrder() { Order = new Order(); }
Testowanie funkcjonalności wyewidencjonowania
W programie Visual Studio Code wybierz pozycję F5. Lub w menu Uruchom wybierz pozycję Rozpocznij debugowanie.
Aplikacja powinna zostać skompilowana, ale jeśli utworzysz zamówienie i spróbujesz wyewidencjonować, zostanie wyświetlony błąd środowiska uruchomieniowego. Ten błąd występuje, ponieważ nasza baza danych pizza.db SQLLite została utworzona przed utworzeniem obsługi zamówień i pizz. Musimy usunąć plik, aby można było poprawnie utworzyć nową bazę danych.
Aby zatrzymać aplikację, wybierz pozycję Shift + F5.
W Eksploratorze plików usuń plik pizza.db .
Wybierz F5. Lub w menu Uruchom wybierz pozycję Rozpocznij debugowanie.
W ramach testu dodaj pizze, przejdź do kasy i złożyć zamówienie. Nastąpi przekierowanie do strony głównej i zobaczysz, że zamówienie jest teraz puste.
Aby zatrzymać aplikację, wybierz pozycję Shift + F5.
Aplikacja się poprawia. Mamy konfigurację pizzy i kasę. Chcemy zezwolić klientom na sprawdzenie stanu zamówienia pizzy po jego złożenia.
Dodawanie strony zamówień
W Eksploratorze plików rozwiń węzeł Strony, kliknij prawym przyciskiem myszy folder i wybierz pozycję Nowy plik.
Nadaj nowemu plikowi nazwę MyOrders.razor. W tym pliku napisz następujący kod:
@page "/myorders" @inject HttpClient HttpClient @inject NavigationManager NavigationManager <div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab"> <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> <a href="myorders" class="nav-tab active"> <img src="img/bike.svg" /> <div>My Orders</div> </a> </div> <div class="main"> @if (ordersWithStatus == null) { <text>Loading...</text> } else if (!ordersWithStatus.Any()) { <h2>No orders placed</h2> <a class="btn btn-success" href="">Order some pizza</a> } else { <div class="list-group orders-list"> @foreach (var item in ordersWithStatus) { <div class="list-group-item"> <div class="col"> <h5>@item.Order.CreatedTime.ToLongDateString()</h5> Items: <strong>@item.Order.Pizzas.Count()</strong>; Total price: <strong>£@item.Order.GetFormattedTotalPrice()</strong> </div> <div class="col"> Status: <strong>@item.StatusText</strong> </div> @if (@item.StatusText != "Delivered") { <div class="col flex-grow-0"> <a href="myorders/" class="btn btn-success"> Track > </a> </div> } </div> } </div> } </div> @code { List<OrderWithStatus> ordersWithStatus = new List<OrderWithStatus>(); protected override async Task OnParametersSetAsync() { ordersWithStatus = await HttpClient.GetFromJsonAsync<List<OrderWithStatus>>( $"{NavigationManager.BaseUri}orders"); } }
Nawigacja musi ulec zmianie na wszystkich stronach, które musimy teraz dołączyć do nowej strony Moje zamówienia . Otwórz plik Checkout.razor i Index.razor i zastąp nawigację następującym kodem:
<div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <a href="" class="nav-tab active" > <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </a> <a href="myorders" class="nav-tab" > <img src="img/bike.svg" /> <div>My orders</div> </a> </div>
Za pomocą
<a>
elementów możemy ręcznie zarządzać aktywną stroną, dodając klasęactive
css. Zaktualizujmy całą nawigację , aby zamiast tego użyć składnika NavLink .Na wszystkich trzech stronach z nawigacją (Index.razor, Checkout.razor i MyOrders.razor) użyj tego samego kodu Blazor do nawigacji:
<div class="top-bar"> <a class="logo" href=""> <img src="img/logo.svg" /> </a> <NavLink href="" class="nav-tab" Match="NavLinkMatch.All"> <img src="img/pizza-slice.svg" /> <div>Get Pizza</div> </NavLink> <NavLink href="myorders" class="nav-tab"> <img src="img/bike.svg" /> <div>My Orders</div> </NavLink> </div>
Klasa
active
css jest teraz automatycznie dodawana do stron przez składnik NavLink . Nie musisz pamiętać, aby zrobić to na każdej stronie, na której znajduje się nawigacja.Ostatnim krokiem jest zmiana
NavigationManager
na przekierowanie do strony po złożeniumyorders
zamówienia. W Eksploratorze plików rozwiń węzeł Pages, a następnie wybierz pozycję Checkout.razor.Zmień metodę
PlaceOrder
, aby przekierować do poprawnej strony, przekazując/myorders
do metody :NavigationManager.NavigateTo()
async Task PlaceOrder() { isSubmitting = true; var response = await HttpClient.PostAsJsonAsync($"{NavigationManager.BaseUri}orders", OrderState.Order); var newOrderId = await response.Content.ReadFromJsonAsync<int>(); OrderState.ResetOrder(); NavigationManager.NavigateTo("/myorders"); }
W programie Visual Studio Code wybierz pozycję F5. Lub w menu Uruchom wybierz pozycję Rozpocznij debugowanie.
Powinno być możliwe zamawianie pizzy, a następnie wyświetlanie zamówień aktualnie w bazie danych.
Zatrzymaj aplikację, wybierając pozycję Shift + F5.