React 项目中的容器划分规范:从架构到落地命名(CSS Modules / Tailwind 版)

本文面向 React 项目实践,系统讲清两件事:

  1. 容器(Container)到底怎么划分:页面、布局、模块、组件各层职责边界是什么?
  2. 在 CSS Modules / Tailwind 下怎么命名与组织容器类:做到可读、可维护、可复用。

如果你经常在代码评审里看到“又多包了一层 div”,或者 PRD 里写“外面那一层”,这篇文章会帮你把命名和分层体系建立起来。


一、React 中“容器”的核心概念:职责驱动,不是 div 驱动

在 React 项目里,“容器”本质不是 DOM 元素,而是承担某类职责的层
同一个容器可能是

code
div
,也可能是
code
main/section
,也可能是一个组件(Container Component)。

一个容器的职责通常来自以下一种或多种:

  • Layout:结构布局(header/sidebar/content)、flex/grid、响应式
  • Spacing:统一边距、对齐、最大宽度
  • Scroll:滚动区域、sticky、可视区控制
  • State / Data:请求、缓存、分页、筛选、表单状态
  • Interaction Layer:overlay、modal、tooltip 等脱离文档流的层

二、React 项目推荐的容器层级(由外到内)

目标:每一层“能说清楚它为什么存在”。

一个“可解释”的页面结构通常是:

<RoutePage> <PageShell> // 页面框架:头/侧/底(可选) <PageContainer> // 控制 max-width / padding / 居中(常用) <ContentLayout> // grid / flex 结构(可选) <Section> // 业务区块:可拆分、可复用 <FeatureModule> // 特性模块:带状态/逻辑(可选) <Widget/> // 纯 UI 组件 ```

1) Route Page(路由页组件)

命名

code
UsersPage.tsx
/
code
UserDetailPage.tsx
职责

  • 与路由绑定、组装页面
  • 放页面级 meta、埋点、权限判断
  • 不做复杂 UI 细节

2) PageShell(页面壳/框架)

命名

code
DashboardShell
/
code
AppShell
职责

  • 页头、侧边栏、底部、全局布局
  • 处理整体布局栅格(例如 sidebar + main)

3) PageContainer(页面容器)

命名

code
PageContainer
/
code
Container
职责

  • 最大宽度、居中、统一 padding
  • 通常是全局通用组件(复用率高)

4) ContentLayout(内容布局容器)

命名

code
TwoColLayout
/
code
SplitLayout
/
code
GridLayout
职责

  • 仅布局(grid/flex),不带业务含义

5) Section(业务区块容器)

命名

code
ProfileSection
/
code
FiltersSection
职责

  • 一个页面中的一块区域
  • 通常对应一个子标题/卡片块

6) FeatureModule(功能模块容器,Container Component)

命名

code
UserListContainer
/
code
UserFiltersContainer
职责

  • 请求数据、管理状态、拼装 UI
  • 将“数据与展示”解耦:容器负责数据,子组件负责展示

三、React 中常用容器划分规范(建议直接写进团队规范)

规范 A:页面组件只做“组装”,业务逻辑下沉到 Feature

Page 负责:

  • 布局骨架
  • 把 Feature 按区域放进去

Feature 负责:

  • 请求、分页、筛选、表单、状态机
  • 暴露清晰的 props 给 UI

✅ 优点:页面稳定、模块可复用、测试更容易。


规范 B:布局容器和业务容器分离

不要把

code
display: grid
code
max-width
code
padding
写进业务模块里。

  • code
    PageContainer
    :只管宽度/边距
  • code
    Layout
    :只管 grid/flex
  • code
    Module/Section
    :只管业务语义与内容

✅ 优点:视觉改版时只动 layout/container,不伤业务组件。


规范 C:滚动容器明确标注(特别是后台系统)

当你使用“局部滚动”而不是 body 滚动时,一定要显式命名:

  • code
    ScrollArea
  • code
    Scrollable
  • code
    ContentScroll

并且统一管理:

  • 谁滚动
  • 哪些元素 sticky
  • scroll restoration 是否需要

规范 D:Overlay 层必须单独抽象(Portal + z-index 体系)

浮层相关组件建议统一从

code
OverlayProvider
code
PortalRoot
出口渲染,避免 z-index 互相打架。

命名上要明确:

  • code
    Overlay
  • code
    Backdrop
  • code
    ModalLayer
  • code
    FloatingLayer

四、CSS Modules 下的容器命名策略(强烈推荐)

CSS Modules 的关键是:类名局部作用域,你不需要用很长的前缀避免冲突,但仍然要让“语义清晰”。

1) 建议的命名模型:
code
角色 + 可选修饰

  • code
    container
  • code
    wrapper
  • code
    layout
  • code
    content
  • code
    section
  • code
    header
  • code
    body
  • code
    footer
  • code
    scrollArea
  • code
    overlay
  • code
    backdrop

示例(UserList.module.css):

css
.container {}
.header {}
.body {}
.footer {}

.filtersSection {}
.tableSection {}

.scrollArea {}
.emptyState {}
.loadingState {}

一个模块的 CSS Modules 文件里,推荐出现一个

code
container
作为根类,其余按区域拆分。


2) 状态类统一用语(推荐)

在 CSS Modules 中状态类非常好用:

  • code
    isLoading
  • code
    isEmpty
  • code
    isDisabled
  • code
    isActive
  • code
    hasError

示例:

css
.container {}
.isLoading {}
.hasError {}

在组件中:

tsx
<div className={clsx(styles.container, loading && styles.isLoading)} />

3) 结构类命名:遵循“DOM 结构可视化”

你看到类名就能在脑内画出 DOM:

  • code
    header
    ,
    code
    toolbar
    ,
    code
    actions
  • code
    content
    ,
    code
    main
    ,
    code
    aside
  • code
    left
    ,
    code
    right
    (仅在布局组件中出现)
  • code
    row
    ,
    code
    col
    (仅在 grid/flex 布局组件中出现)

4) 不推荐的 CSS Modules 命名(反例)

code
box1
,
code
box2
,
code
leftBox
(缺乏语义) ❌
code
wrap
,
code
wrap2
(维护困难) ❌
code
containerA
,
code
containerB
(没表达职责)


五、Tailwind 下的容器命名策略(核心:命名组件,而不是命名 class)

Tailwind 的世界里,你往往不会写

code
.container {}
,而是直接写:

tsx
<div className="mx-auto max-w-6xl px-6">

但当页面复杂后,你必须用“命名组件/变量”来替代“命名 class”,否则 class 会爆炸。

策略 1:把“容器语义”抽成组件(最推荐)

例如统一页面容器:

tsx
export function PageContainer({ children }: { children: React.ReactNode }) {
  return <div className="mx-auto w-full max-w-6xl px-6">{children}</div>;
}

统一 section:

tsx
export function Section({ title, children }: { title?: string; children: React.ReactNode }) {
  return (
    <section className="rounded-2xl border p-4">
      {title && <h2 className="mb-3 text-lg font-semibold">{title}</h2>}
      {children}
    </section>
  );
}

Tailwind 下最好的“命名策略”是:把语义放到组件名里。


策略 2:对重复 class 使用常量/组合函数

当不想抽组件时,用常量也行:

tsx
const pageContainer = "mx-auto w-full max-w-6xl px-6";
const sectionCard = "rounded-2xl border bg-white p-4";

策略 3:用 tailwind-variants / clsx 做语义化变体

(你不用立刻上库,思路先记住)

  • code
    variant
    : size / tone / layout
  • code
    state
    : loading / disabled / selected

策略 4:用 Tailwind 的约定命名“语义块”

即使不写 CSS,你也要在组件层表达:

  • code
    PageShell
  • code
    ContentLayout
  • code
    Sidebar
  • code
    Toolbar
  • code
    ScrollArea
  • code
    Overlay

Tailwind 的可维护性来自组件分层,而不是 class 的整洁。


六、CSS Modules vs Tailwind:容器命名的统一原则

无论你用哪一种,统一遵循这条:

命名表达职责,不表达实现。

code
scrollArea
(职责:滚动) ❌
code
overflowAutoDiv
(实现:overflow auto)

code
layout
/
code
twoColLayout
(职责:布局) ❌
code
gridDiv
(实现:grid)


七、推荐的团队级“容器词汇表”(直接贴到规范里)

结构容器

  • code
    page
    ,
    code
    shell
    ,
    code
    container
    ,
    code
    content
    ,
    code
    layout
    ,
    code
    section
    ,
    code
    module

组件包裹

  • code
    wrapper
    ,
    code
    root
    ,
    code
    inner
    ,
    code
    outer

交互 / 浮层

  • code
    overlay
    ,
    code
    backdrop
    ,
    code
    layer
    ,
    code
    portalRoot
    ,
    code
    floating

滚动与定位

  • code
    scrollArea
    ,
    code
    stickyHeader
    ,
    code
    affix
    ,
    code
    viewport

区域与动作

  • code
    header
    ,
    code
    toolbar
    ,
    code
    actions
    ,
    code
    body
    ,
    code
    footer
    ,
    code
    aside
    ,
    code
    main

八、一个完整示例(React + 容器分层 + 命名)

code
UsersPage
└── DashboardShell
    └── PageContainer
        ├── PageHeaderSection
        ├── FiltersSection
        └── UsersTableSection
            └── UsersTableContainer
                └── UsersTableView

你会发现:

  • Page:只组装
  • Shell/Container/Layout:只管结构
  • Section/Module:表达业务区域
  • Container Component:承载数据逻辑
  • View/UI:纯展示

九、落地检查清单(写代码前 10 秒自检)

  • 这一层存在的理由是什么?(宽度/布局/滚动/状态/浮层?)
  • 它是否应该抽为通用容器组件?
  • 命名是否表达职责?(container/section/layout/overlay/scroll)
  • Tailwind 中是否出现“重复 class”?是否该抽组件/常量?
  • CSS Modules 中是否出现“无语义命名”?(box1/wrap2)

结语

容器分层与命名不是“洁癖”,它解决的是三个核心问题:

  1. 让页面结构可解释
  2. 让布局与业务解耦
  3. 让多人协作沟通成本下降

当你把

code
container / layout / section / module / overlay / scrollArea
这些词用准了,代码会更像工程,而不是堆叠的 div。


你可以继续扩展的方向(可选)

  • React Server Components / Next.js App Router 下的容器分层
  • Design System 中容器组件库的抽象方法
  • z-index 管理与 overlay 体系(Portal Root 规范)
code

---

如果你还想更“工程化”,我可以再给你补两块(都很实用,直接能进团队规范):
1) **一个推荐的目录结构**(pages/features/components/layouts/styles)  
2) **一套容器组件库模板**(PageContainer / Section / ScrollArea / Overlay)带 TypeScript 类型

你要我继续把这两块也写成 md 吗?

评论

还没有评论,来做第一个留言的人吧。

发表评论

验证码: