Blog Detail

组件拆分应该怎么练

从一个页面拆出更小、更清楚的组件,是前端很重要的基本功。

2026-05-08·9 分钟阅读·8 个章节
React组件设计

一、组件拆分不是为了“文件变多”

我以前对组件拆分有个误解,总觉得它会让项目里多很多文件,看起来更复杂。后来我才慢慢意识到,拆分真正的目的不是“文件数量”,而是让每个文件只承担一种清楚的责任。

比如:

  • PostCard 只负责展示文章卡片
  • SiteHeader 只负责导航
  • ThemeToggle 只负责主题切换

当职责足够单一时,后面排查问题会轻松很多。

二、一个组件什么时候开始危险

我一般会把下面这些信号当作“组件快失控了”的提醒:

信号说明
文件越来越长说明职责开始堆叠
JSX 重复很多说明有重复结构可以提取
同时处理数据、交互、样式说明边界不清
改一小点却要看半天说明可读性已经下降

如果一个组件同时负责请求数据、处理状态、弹窗、筛选、分页、展示和跳转,那它基本已经不是一个“单一职责组件”了。

三、我会怎么拆一个页面

我现在更喜欢从页面结构开始往下拆。

比如博客列表页,我不会一上来就写 200 行 JSX,而会先想成这样:

tsx
<main>
  <BlogHero />
  <BlogFilterPanel />
  <BlogPostResults />
  <BlogPagination />
</main>

这时候页面组件只负责组织区块,真正的展示细节交给子组件。

这个思路的好处是:页面层看起来像目录,而不是像一大坨实现细节。

四、什么时候该抽成通用组件

如果某块结构在两个页面里都会出现,我就会开始考虑是不是值得通用化。

例如:

  • 标题区块:SectionHeading
  • 标签集合:TagList
  • 文章卡片:PostCard
  • 项目卡片:ProjectCard

这种组件有一个共同点:它们展示的是“某一类稳定结构”,而不是页面里的临时逻辑。

五、一个不好的拆分长什么样

并不是拆得越细越好。

如果你把一个很自然的结构硬拆成:

  • CardTitle
  • CardDescription
  • CardFooterAction
  • CardMetaRow

但这些东西只在一个地方用,而且拆完后反而要来回跳文件,那就不是好的拆分。

好的拆分应该满足两件事:

  1. 读页面时更容易理解
  2. 修改某块时更容易定位

六、命名为什么影响这么大

命名会直接影响你能不能快速理解组件责任。

下面这个例子就很典型:

ts
const data = [];
const item = {};
const handleClick = () => {};

这些名字不是错,但太泛了。过两周再回来,你很难第一眼知道它们到底在处理什么。

相比之下:

ts
const blogPosts = [];
const selectedPost = {};
const handleOpenPostDetail = () => {};

会清楚很多。

组件名也是一样。PostCard 一看就知道是文章卡片,ThingBox 就完全没有帮助。

七、我现在会怎么判断“该不该拆”

我通常会问自己 3 个问题:

  1. 这块 JSX 会不会复用?
  2. 这块是不是已经有独立职责?
  3. 拆出去之后,页面是不是更容易读?

如果三个问题里有两个答案是“会”,那就很值得拆。

八、一个很实际的小原则

对初学阶段来说,我觉得“一个文件先尽量控制在 100 行左右”是个很有帮助的提醒。

这不是死规则,但它会逼着我在文件变大之前先停下来想一想:

  • 这里是不是已经有重复结构了?
  • 这里的逻辑是不是能挪出去?
  • 这个组件是不是开始承担太多事了?

很多可维护性问题,其实都是在文件变得太大时才慢慢显形的。