Mẫu Thiết Kế Frontend: Hướng Dẫn Thực Hành Toàn Diện
Hướng dẫn này tập trung vào các mẫu thiết kế thực tiễn mà bạn có thể áp dụng ngay hôm nay trong React/Next.js (nhưng hầu hết các khái niệm là không phụ thuộc vào framework).
Mục Lục
- Nguyên Tắc Cốt Lõi
- Mẫu Thành Phần
- Mẫu Quản Lý Trạng Thái
- Truy Xuất Dữ Liệu & Ranh Giới
- Mẫu Tạo Kiểu
- Mẫu Hiệu Suất
- Mẫu Kiến Trúc
- Mẫu Kiểm Tra
- Tiếp Cận & Trải Nghiệm Người Dùng
- Xử Lý Lỗi & Độ Tin Cậy
- Danh Sách Kiểm Tra (TL;DR)
Nguyên Tắc Cốt Lõi
- Kết hợp hơn thừa kế: xây dựng các phần nhỏ và kết hợp chúng.
- Trách nhiệm đơn lẻ: mỗi thành phần thực hiện một nhiệm vụ tốt.
- Nâng trạng thái lên chỉ khi nhiều con cần nó.
- Ưu tiên thành phần thuần túy/được kiểm soát để dễ dự đoán.
- Đặt logic, kiểu dáng, kiểm tra gần thành phần.
Mẫu Thành Phần
1) Thành Phần Hiển Thị và Thành Phần Container (Thông Minh/Ngốc Ngếch)
- Thành phần hiển thị: chỉ UI, nhận dữ liệu qua props.
- Thành phần container: xử lý việc truy xuất dữ liệu/trạng thái, truyền props xuống.
javascript
// Thành phần Container
function UserCardContainer() {
const { data } = useQuery({ queryKey: ['user'], queryFn: fetchUser })
return <UserCard user={data} />
}
// Thành phần Hiển Thị
function UserCard({ user }) {
return <div className="card">Xin chào, {user.name}</div>
}
2) Thành Phần Kiểm Soát và Không Kiểm Soát
- Kiểm soát: giá trị sống trong trạng thái React.
- Không kiểm soát: DOM giữ giá trị; bạn đọc refs khi cần.
javascript
// Thành phần Kiểm Soát
function NameInputControlled() {
const [name, setName] = useState('')
return <input value={name} onChange={e => setName(e.target.value)} />
}
// Thành phần Không Kiểm Soát
function NameInputUncontrolled() {
const ref = useRef(null)
const submit = () => console.log(ref.current?.value)
return <><input ref={ref} /><button onClick={submit}>Lưu</button></>
}
3) Thành Phần Tổ Hợp
Để cha sở hữu trạng thái; trẻ em giao tiếp qua ngữ cảnh.
javascript
const TabsContext = createContext(null)
export function Tabs({ children }) {
const [active, setActive] = useState(0)
return <TabsContext.Provider value={{active, setActive}}>{children}</TabsContext.Provider>
}
Tabs.List = function List({ children }) { return <div role="tablist">{children}</div> }
Tabs.Tab = function Tab({ index, children }) {
const ctx = useContext(TabsContext)
return <button role="tab" aria-selected={ctx.active===index} onClick={() => ctx.setActive(index)}>{children}</button>
}
Tabs.Panel = function Panel({ index, children }) {
const ctx = useContext(TabsContext)
return ctx.active===index ? <div role="tabpanel">{children}</div> : null
}
4) Render Props / HOCs / Custom Hooks
- Ưu tiên custom hooks trong React hiện đại để tái sử dụng logic.
javascript
// Custom hook (logic)
function useCountdown(ms: number) {
const [left, setLeft] = useState(ms)
useEffect(() => { const id = setInterval(() => setLeft(v => Math.max(0, v-1000)), 1000); return () => clearInterval(id) }, [])
return left
}
// Sử dụng
function OfferTimer() {
const left = useCountdown(10_000)
return <p>Thời gian còn lại: {Math.ceil(left/1000)}s</p>
}
Mẫu Quản Lý Trạng Thái
- Trạng thái UI cục bộ:
useState/useReducer(biểu mẫu, công tắc). - Trạng thái suy diễn: tính toán từ trạng thái nguồn; tránh sao chép.
- Trạng thái toàn cầu: chỉ cho dữ liệu xuyên suốt (auth, theme). Sử dụng Context, Zustand, Redux Toolkit, hoặc Jotai.
- Trạng thái máy chủ: sử dụng React Query/SWR (caching, refetching, dedup).
javascript
// Ví dụ trạng thái máy chủ với React Query
const { data, isLoading, error } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })
- Máy trạng thái: XState/Zustand FSM cho quy trình phức tạp (trạng thái rõ ràng, chuyển tiếp).
Truy Xuất Dữ Liệu & Ranh Giới
- Suspense cho ranh giới UI không đồng bộ (fallback tải).
- Ranh giới lỗi cho lỗi render không bắt được.
- Skeletons cho hiệu suất cảm nhận.
- Phân trang/Tải không giới hạn để tránh tải trọng lớn.
javascript
// Ranh giới lỗi (đơn giản)
class ErrorBoundary extends React.Component {
state = { hasError: false }
static getDerivedStateFromError() { return { hasError: true } }
render() { return this.state.hasError ? <p>Có gì đó không đúng.</p> : this.props.children }
}
Mẫu Tạo Kiểu
- Utility‑first: Tailwind cho tính nhất quán + tốc độ.
- CSS Modules: phân vùng có thể dự đoán.
- CSS‑in‑JS (MUI emotion/styled-components): kiểu dáng động, chủ đề.
- Design tokens: một nguồn sự thật cho màu sắc/khoảng cách/typography.
javascript
// MUI theme tokens
const theme = createTheme({
palette: { primary: { main: '#0d6efd' } },
shape: { borderRadius: 12 },
})
Mẫu Hiệu Suất
- Memoization:
useMemo,useCallback,React.memocho công việc/props tốn kém. - Virtualization:
react-windowcho danh sách lớn. - Code splitting: nhập động để giảm JS ban đầu.
- Tránh re‑renders: key props, stable handlers, co-locate state.
javascript
const Chart = dynamic(() => import('./Chart'), { ssr: false })
Mẫu Kiến Trúc
- Thiết Kế Nguyên Tử (Atoms/Molecules/Organisms/Templates/Pages).
- Thiết Kế Phân Chia Tính Năng: theo miền (entities/features/shared).
- Gói Monorepo (PNPM/Turbo): chia sẻ UI + utils.
- Micro‑frontends (Module Federation): cho các tổ chức rất lớn (sử dụng tiết kiệm).
Mẫu Kiểm Tra
- Đơn vị: hàm/thành phần thuần túy (Jest/Vitest).
- Tích hợp: các thành phần với trẻ em thực tế (React Testing Library).
- E2E: quy trình người dùng (Playwright/Cypress). Ưu tiên kiểm tra hành vi, không phải chi tiết thực hiện.
javascript
// Ví dụ RTL
render(<Button onClick={fn} />)
await user.click(screen.getByRole('button'))
expect(fn).toHaveBeenCalled()
Tiếp Cận & Trải Nghiệm Người Dùng
- Sử dụng HTML ngữ nghĩa và các vai trò ARIA.
- Quản lý tiêu điểm (modals, menus).
- Đảm bảo hỗ trợ bàn phím và máy đọc màn hình.
- Độ tương phản màu sắc, prefers‑reduced‑motion, i18n/rtl.
Xử Lý Lỗi & Độ Tin Cậy
- Các fallback duyên dáng, thử lại với backoff, UI ngoại tuyến/tối ưu.
- Hệ thống thông báo/cảnh báo tập trung.
javascript
toast.promise(api.save(data), {
loading: 'Đang lưu…',
success: 'Đã lưu!',
error: 'Lưu không thành công',
})
Danh Sách Kiểm Tra (TL;DR)
- [ ] Tách UI khỏi dữ liệu/tác động bên.
- [ ] Tái sử dụng logic qua custom hooks.
- [ ] Chọn phạm vi trạng thái phù hợp (cục bộ/toàn cầu/máy chủ).
- [ ] Thêm ranh giới (tải/lỗi).
- [ ] Tạo kiểu với tokens + hệ thống nhất quán.
- [ ] Theo dõi re‑renders, chia tách mã, ảo hóa danh sách.
- [ ] Kim tự tháp kiểm tra: đơn vị → tích hợp → E2E.
- [ ] Gửi UX có thể truy cập, đáng tin cậy.
Kết Luận
Bài viết này đã cung cấp một cái nhìn tổng quan về các mẫu thiết kế frontend mà bạn có thể áp dụng ngay. Hãy bắt đầu thử nghiệm với các mẫu này trong dự án của bạn để cải thiện cấu trúc và hiệu suất của ứng dụng. Nếu bạn thấy bài viết hữu ích, đừng quên chia sẻ và theo dõi để cập nhật thêm nhiều kiến thức mới!