🧱 如何设计一个“真正可复用”的前端组件?
🔧 一个按钮可以写10次,也可以封装一次复用全场;组件是前端的积木,而设计模式才是组装它们的说明书。你真的在写“可复用”组件吗?
🧠 什么是可复用组件?
所谓“可复用”,不仅是复制粘贴组件这么简单,而是:
✅ 能跨多个页面/模块使用
✅ 能被复合、嵌套、组合
✅ 能支持灵活配置和扩展
✅ 能隔离内部逻辑,隐藏实现细节
✅ 能在多个项目中迁移使用(库化)
🧩 核心原则一:面向配置编程(Props 设计)
以一个弹窗组件为例:
<Modaltitle="提示"visible={visible}onClose={() => setVisible(false)}footer={<CustomFooter />}
/>
✅ 好的 Props 应该:
特性 | 示例 |
---|---|
🧠 可读性强 | title="登录提示" 比 t="登录" 好 |
🧩 支持组合 | footer 支持传 JSX 或隐藏 |
🎯 默认值合理 | closable=true 不传也能用 |
🚀 高扩展性 | beforeClose() 钩子支持拦截关闭 |
🧩 核心原则二:关注点分离(拆 UI 和逻辑)
避免在组件中同时处理:
- UI 渲染
- 状态管理
- 数据获取
- 事件逻辑
✅ 推荐:UI 组件 + Hook/Composable 分离逻辑
React 示例(Hooks):
function useModal() {const [visible, setVisible] = useState(false);const open = () => setVisible(true);const close = () => setVisible(false);return { visible, open, close };
}
组件层只负责渲染:
<Modal visible={visible} onClose={close} />
Vue 示例(Composable):
export function useModal() {const visible = ref(false);const open = () => (visible.value = true);return { visible, open };
}
🧩 核心原则三:插槽 & Render Props 让组件更灵活
Vue 中使用 slot
:
<CustomTable><template #toolbar><Button>新增</Button></template>
</CustomTable>
React 中使用 children
或 render props:
<TablerenderToolbar={() => (<Button>新增</Button>)}
/>
插槽 / Render Props 是组件复用的“开放式接口”。
🧩 核心原则四:可组合的组件设计(组合 > 继承)
一个“组合式”的 Form 组件架构 👇
<Form><Form.Item label="用户名"><Input /></Form.Item><Form.Item label="密码"><Input type="password" /></Form.Item>
</Form>
Form
管理上下文(如验证、收集值)Form.Item
管理 label、错误提示Input
专注输入逻辑
优点:
- ✅ 结构清晰
- ✅ 容易插拔/扩展
- ✅ 内聚逻辑解耦封装
🔧 技术加持:让组件更强大的方法
技术 | 作用 |
---|---|
TypeScript 泛型 | 精确 props 类型,支持 IDE 提示 |
事件派发 / 自定义事件 | 组件内向外传递操作 |
Context / Provide/Inject | 实现跨层通信 |
组合式函数(Hooks/Composables) | 提取公共逻辑 |
主题系统 / 样式变量 | 实现定制化风格 |
🧪 示例:一个「超可复用」的 Table 组件设计思路
✅ 配置式 + 插槽:
<Tablecolumns={[{ title: '名称', dataIndex: 'name' },{ title: '年龄', dataIndex: 'age', render: val => <Tag>{val}</Tag> },]}dataSource={data}
/>
✅ 扩展:支持分页、loading、自定义操作栏、空状态提示等:
<Tablecolumns={columns}dataSource={data}loading={loading}pagination={{ current: 1, pageSize: 10 }}emptyTip={<Empty description="暂无数据" />}
/>
这样封装后,整套表格系统可被复用于几十个页面。
⚠️ 不可复用组件的常见“反模式”
反模式 | 问题 |
---|---|
Props 拆得太碎 | 使用复杂,传值不直观 |
写死业务逻辑 | 拖不动、迁不走、复用不了 |
没有状态控制出口 | 用户无法控制内部行为 |
样式不隔离 | 每次引入就“爆炸” |
接口数据写死在组件里 | 不通用,只能在一个项目用 |
🧠 总结:可复用组件的五个关键特性
- ✅ 低耦合:功能单一,职责清晰
- ✅ 高内聚:UI 与状态适度绑定
- ✅ 可组合:支持嵌套、插槽、自定义结构
- ✅ 可配置:props + config 驱动行为
- ✅ 可扩展:暴露必要事件、方法,便于集成与增强
组件写得好,维护效率能提升一个维度;写得乱,整个项目都跟着混乱。
👍 如果你觉得这篇文章有帮助,欢迎点赞、关注、收藏,下一篇为大家带来《如何打造一个通用表单生成器组件系统》