Khác với các ứng dụng web truyền thống phải tải lại toàn bộ trang, Blazor Server sử dụng một kết nối thời gian thực để cập nhật giao diện người dùng (UI) một cách linh hoạt và tức thì.
1. Cơ chế vận hành: Sức mạnh từ SignalR
Điểm khác biệt lớn nhất của Blazor Server (nay gọi là Interactive Server) so với MVC hay Razor Pages truyền thống là Stateful Connection:
- Khi trình duyệt kết nối, một kênh SignalR (dựa trên WebSockets) được thiết lập.
- Toàn bộ logic UI và trạng thái component chạy trên server.
- Mỗi khi có sự kiện người dùng (click, gõ phím...), server chỉ tính toán phần thay đổi nhỏ nhất của HTML (gọi là UI diff) và gửi đoạn dữ liệu cực nhỏ về trình duyệt để cập nhật giao diện.
2. Cấu trúc một ứng dụng Blazor Web App (.NET 10)
Từ .NET 8 trở đi, Microsoft khuyến nghị sử dụng template Blazor Web App. Cấu trúc thư mục tiêu chuẩn thường như sau:
- Components/Pages/: Chứa các trang chính của ứng dụng (các file có directive @page).
- Components/Layout/: Chứa các layout chung như MainLayout.razor, NavMenu.razor...
- wwwroot/: Nơi đặt CSS, hình ảnh, JavaScript và các file tĩnh.
- App.razor: Định nghĩa Router và render mode mặc định.
- Program.cs: Nơi đăng ký Dependency Injection và các dịch vụ.
Ví dụ
Home.razor@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
Layout
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
App.razor: Đây là file HTML đầu tiên được render. Nó đóng vai trò là "vỏ bọc" bên ngoài cùng, định nghĩa cấu trúc trang web tiêu chuẩn (<html>, <head>, <body>).
- <Routes />: Thành phần này kích hoạt hệ thống định tuyến (Routing).
- <script src="_framework/blazor.web.js">: Đây là đoạn mã quan trọng nhất ở phía client. Nó chịu trách nhiệm thiết lập kết nối SignalR với server và quản lý việc cập nhật DOM.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<ResourcePreloader />
<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["BlazorGettingStarted.styles.css"]" />
<ImportMap />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
</head>
<body>
<Routes />
<ReconnectModal />
<script src="@Assets["_framework/blazor.web.js"]"></script>
</body>
</html>
App.route: File này chứa component - Found: Nếu tìm thấy trang phù hợp, nó sẽ bao bọc trang đó trong một DefaultLayout (thường là MainLayout).
- NotFound: Hiển thị nội dung khi người dùng truy cập vào đường dẫn không tồn tại.
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>
3. Hai chế độ thiết lập Render Mode (Interactive Server)
Trong Blazor Web App (.NET 10), bạn có hai cách chính để áp dụng Interactive Server:
a. Cấp độ toàn bộ ứng dụng (Global)
Phù hợp khi bạn muốn hầu hết các trang đều tương tác mạnh mẽ với SignalR.
Trong file App.razor:
<Routes @renderMode="InteractiveServer" />
b. Cấp độ từng trang/component (Per-page / Per-component)
Rất linh hoạt, đặc biệt khi bạn muốn kết hợp Static SSR (tốt cho SEO) với các trang cần tương tác.
Ví dụ trang Dashboard:
@page "/dashboard"
@rendermode InteractiveServer
<h1>Dashboard tương tác</h1>
4. Thành phần của một Component (.razor)
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Bộ đếm: @currentCount</h1>
<button class="btn btn-primary" @onclick="IncrementCount">
Tăng số
</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
5. Giao tiếp giữa các Component
Khi xây dựng ứng dụng lớn, bạn sẽ chia nhỏ UI thành nhiều component con:
- Truyền dữ liệu từ cha xuống con: Sử dụng thuộc tính [Parameter].
- Truyền sự kiện từ con lên cha: Sử dụng EventCallback.
6. Quản lý trạng thái và Dependency Injection (DI)
Blazor tận dụng hoàn hảo hệ thống DI của .NET với 3 vòng đời chính:
- Singleton: Dùng chung toàn ứng dụng.
- Scoped: Tồn tại theo Circuit (phiên kết nối của từng người dùng) – lý tưởng cho thông tin đăng nhập, giỏ hàng tạm thời.
- Transient: Tạo mới mỗi lần gọi.
7. Lifecycle Methods
Các phương thức lifecycle quan trọng:
- OnInitializedAsync(): Load dữ liệu ban đầu (chạy một lần).
- OnParametersSetAsync(): Chạy khi tham số từ cha thay đổi.
- OnAfterRenderAsync(): Sau khi UI render xong (dùng cho JS interop).
- StateHasChanged(): Thủ công trigger re-render.
Lời kết
Phase 1 này đã giúp bạn hình dung bức tranh tổng quan về Blazor Server (Interactive Server) trong .NET 10. Với hai chế độ thiết lập render mode linh hoạt, bạn có thể cân bằng giữa hiệu năng, SEO và trải nghiệm tương tác.
Trong các bài viết tiếp theo, chúng ta sẽ đi sâu vào Authentication & Authorization, tích hợp Entity Framework Core, và tối ưu hiệu năng cho ứng dụng Blazor thực tế.
Bạn đang dùng render mode nào nhiều nhất? Hãy để lại comment bên dưới nhé!
Nhận xét
Đăng nhận xét