一、组件化思想:什么是组件化、为什么需要组件化、组件化的历史演变、组件化的核心原则

1.1 到底什么是组件化?

先别急着看定义。我换个角度问你:你写代码的时候,有没有复制粘贴过一大段 HTML?

如果有,那你其实已经在「无意识组件化」了。

组件化,说白了就是——把页面拆成一个个独立的小块。每个小块有自己的结构、样式、逻辑。它们可以单独开发、单独测试、单独维护。然后像搭积木一样拼成完整的页面。

举个例子。一个电商的商品卡片:

<!-- 商品卡片组件 -->
<div class="product-card">
  <img src="product.jpg" alt="商品图片" />
  <h3>商品名称</h3>
  <p class="price">¥99.00</p>
  <button>加入购物车</button>
</div>

这个卡片,就是一个组件。它不依赖页面其他部分。你可以在首页用它,在搜索结果页用它,在推荐列表里也用它。改样式?只改这一个地方就行。

核心定义:组件是 UI 中可复用的最小单元。它封装了 HTML、CSS、JavaScript,对外暴露清晰的接口(props / slots / events)。

1.2 为什么需要组件化?

我刚开始做前端那会儿,项目还是「一个 HTML 文件写到底」。一个页面几千行代码,改个按钮颜色得全局搜索替换。你想想看,那是什么体验?

组件化解决了三个最痛的问题:

  • 复用性——同样的功能,写一次就够了。别到处复制粘贴。
  • 可维护性——改一个组件,所有用到的地方自动更新。不用满世界找代码。
  • 协作效率——团队可以并行开发。你写你的按钮,我写我的弹窗,互不干扰。

我在项目中遇到过最典型的场景:一个后台管理系统,光表格就有十几个页面。如果没有组件化,每个页面都要写一遍分页、排序、筛选的逻辑。有了组件化,一个 <DataTable> 搞定所有。

我的经验:组件化带来的最大收益不是「少写代码」,而是「少出 bug」。因为每个组件都被反复测试过,你只管用就行。

1.3 组件化的历史演变

这条路不是一天走出来的。我简单梳理一下:

阶段 代表技术 特点
原始阶段 HTML + CSS + JS 混写 一个页面一个文件,复用靠复制粘贴
模板阶段 ASP / JSP / PHP 包含文件 服务端 include 公共头部、底部
前端模板阶段 jQuery + 模板引擎(如 Handlebars) JS 动态渲染 HTML,开始有「组件」概念
现代框架阶段 React / Vue / Angular 真正的组件化:声明式、响应式、单向数据流
微前端阶段 Module Federation / qiankun 组件可以跨应用、跨团队共享

嗯,这里要注意。很多人以为组件化是 React 发明的。其实不是。早在 2005 年,YUI(Yahoo! User Interface)就已经有了组件化的雏形。只是那时候的组件,还是「用 JS 生成 DOM 节点」这种笨办法。

真正让组件化普及的,是 React 在 2013 年提出的「组件即函数」 这个理念。你想想看,一个函数接收参数、返回 UI,多直观?

1.4 组件化的核心原则

做了这么多年组件库,我总结了四条铁律。违背任何一条,你的组件都会变成「负资产」:

原则一:单一职责

一个组件只做一件事。如果它既展示数据、又处理表单验证、还负责动画效果……那它就不是组件,是「大泥球」。

我曾经踩过的坑:写了一个超级弹窗组件,支持 30 种配置项。结果没人敢用,因为没人能搞懂所有配置。后来拆成 5 个小组件,反而大家都爱用了。

原则二:接口清晰

组件的 props 就是它的「说明书」。命名要直观,类型要明确,默认值要合理。

// 好的接口设计
<Button
  variant="primary"    // primary | secondary | danger
  size="md"            // sm | md | lg
  disabled={false}
  onClick={handleClick}
>
  提交
</Button>

// 坏的接口设计
<Button
  type="1"             // 1 是什么?没人知道
  big={true}           // 用 boolean 控制尺寸?不优雅
  click={handleClick}  // 命名不一致
>
  提交
</Button>

原则三:高内聚、低耦合

组件内部的逻辑要紧密相关(高内聚)。组件之间的依赖要尽可能少(低耦合)。

说白了就是:改一个组件,不应该牵连其他组件。如果改了 A 组件,B 组件也跟着崩了,那你们的耦合度就有问题了。

原则四:可测试

一个组件好不好,看它好不好测。如果一个组件依赖全局状态、依赖 DOM 结构、依赖异步请求……那测试起来就是噩梦。

我的习惯:写组件之前,先想清楚「这个组件的输入是什么?输出是什么?」。输入就是 props,输出就是渲染结果。只要这两样清晰,测试就简单了。

1.5 小结

组件化不是什么高深的概念。它就是把大问题拆成小问题,然后逐个解决。你写代码的时候,多问自己一句:「这段代码以后还会用到吗?」——如果答案是「会」,那就把它抽成组件。

下一章,我会聊聊组件设计的具体方法论。包括怎么划分组件粒度、怎么设计 props 接口、怎么处理组件通信。这些都是实战中真正用得上的东西。

公众号:蓝海资料掘金营,微信deep3321