FSD 各层级最优与错误对照组
本节面向团队实践和规范推进,结合实际项目代码示例,对每一层提供“最优做法(正确)”和“常见反面案例(错误)”对比,直观展现分层价值和常见问题。
1. app 层(全局配置/入口)
最优做法(正确)
1 2 3 4 5 6 7 8 9 10 11
| import { ChakraProvider } from "@chakra-ui/react"; import { AppRouter } from "./router";
export function AppProviders({ children }: { children: React.ReactNode }) { return ( <ChakraProvider> <AppRouter>{children}</AppRouter> </ChakraProvider> ); }
|
反面案例(错误)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { ChakraProvider } from "@chakra-ui/react"; import { BrowserRouter, Routes, Route } from "react-router-dom"; import { UserTableWidget } from "../widgets/UserTable"; import { FilterUsersFeature } from "../features/FilterUsers";
export default function App() { return ( <ChakraProvider> <BrowserRouter> <FilterUsersFeature /> <UserTableWidget /> </BrowserRouter> </ChakraProvider> ); }
|
2. pages 层(页面/路由)
最优做法(正确)
1 2 3 4 5 6 7 8 9 10 11 12
| import { UserTableWidget } from "@/widgets/UserTable"; import { FilterUsersFeature } from "@/features/FilterUsers";
export default function UserPage() { return ( <div> <FilterUsersFeature /> <UserTableWidget /> </div> ); }
|
反面案例(错误)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { useState, useEffect } from "react";
export default function UserPage() { const [users, setUsers] = useState([]); useEffect(() => { fetch("/api/users") .then((r) => r.json()) .then(setUsers); }, []); return ( <div> <input /> {/* 筛选功能直接写在页面 */} <table> <tbody> {users.map((u) => ( <tr key={u.id}> <td>{u.name}</td> <td>{u.email}</td> </tr> ))} </tbody> </table> </div> ); }
|
- 错误点:业务逻辑、状态、副作用、UI 全写进页面,违背单一职责。
最优做法(正确)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import { useUsers } from "@/entities/user"; import { UserRowFeature } from "@/features/UserRow";
export function UserTableWidget() { const { users } = useUsers(); return ( <table> <tbody> {users.map((u) => ( <UserRowFeature key={u.id} user={u} /> ))} </tbody> </table> ); }
|
反面案例(错误)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| export function UserTableWidget({ users }) { return ( <table> <tbody> {users.map((u) => ( <tr key={u.id}> <td>{u.name}</td> <td>{u.email}</td> </tr> ))} </tbody> </table> ); }
|
- 错误点:组件成为“死表格”,没有能力组合 feature/entity,难以扩展。
4. features 层(单一业务能力)
最优做法(正确)
1 2 3 4 5 6 7 8 9 10 11 12
| import { useUserFilter } from "@/entities/user"; export function FilterUsersFeature() { const { filter, setFilter } = useUserFilter(); return ( <input value={filter} onChange={(e) => setFilter(e.target.value)} placeholder="筛选用户" /> ); }
|
反面案例(错误)
1 2 3 4 5 6 7 8 9 10 11
| export function FilterUsersFeature({ users, onFilter }) { return ( <input onChange={(e) => onFilter(users.filter((u) => u.name.includes(e.target.value))) } /> ); }
|
- 错误点:feature 不聚焦自身业务,状态管理混乱、耦合父组件。
5. entities 层(领域数据/模型)
最优做法(正确)
1 2 3 4 5 6 7 8 9 10 11
| export interface User { id: string; name: string; email: string; }
import { fetchUserList } from "@/service-api/user"; export async function getUsers() { return await fetchUserList(); }
|
反面案例(错误)
1 2 3 4 5 6 7 8 9
| export const UserModel = {};
export async function getUsers() { return await fetch("/api/users").then((r) => r.json()); }
|
- 错误点:缺少类型、缺少对 service-api 的抽象和适配。
6. shared 层(通用能力)
最优做法(正确)
1 2 3 4 5
| import { Button as ChakraButton, ButtonProps } from "@chakra-ui/react"; export function Button(props: ButtonProps) { return <ChakraButton {...props} />; }
|
反面案例(错误)
1 2 3 4 5
| export function Button({ label }) { return <button>{label}</button>; }
|
7. service-api 层(后端通信)
最优做法(正确)
1 2 3 4 5
| export async function fetchUserList() { const res = await fetch("/api/users"); return res.json(); }
|
反面案例(错误)
1 2 3 4 5
| export async function fetchUserList() { return fetch("/api/users"); }
|
- 错误点:没有数据解析/错误处理,未抽象出前端可用格式。
总结
- FSD 强调每层只做本层职责,各层通过 public-api 协作,避免耦合与责任重叠。
- 错误分层的常见症状:职责混乱、类型不明、状态乱入、无复用、不可单测。