一、这东西是什么
antd (Ant Design)是阿里巴巴开源的 React UI 组件库,提供丰富的企业级 UI 组件。但 antd 的价值不止于组件本身,更在于其优秀的设计模式应用。
核心观点:antd 和 lodash-es 虽然领域不同,但都应用了相似的设计模式:
- 模块化设计:组件独立,支持按需引入
- 组合模式:通过 props 组合实现复杂功能
- 装饰器模式:高阶组件增强功能
- 工厂模式:统一创建相似组件
二、这东西有什么用
适用场景
- React 项目开发
- 需要高质量 UI 组件的企业应用
- 学习前端设计模式的开发者
- 需要自定义组件库的团队
能带来什么收益
- 代码复用:减少重复代码,提高开发效率
- 可维护性:清晰的架构让代码更易维护
- 一致性:统一的设计模式保证代码风格一致
- 扩展性:易于添加新功能或修改现有功能
三、官方链接
四、从源码看设计模式
1. 模块化设计(与 lodash-es 同款)
javascript
// antd 的模块化结构
// 每个组件独立目录,支持按需引入
import { Button, Modal, Form } from 'antd';
// 或者按需引入特定组件
import Button from 'antd/es/button';
import Modal from 'antd/es/modal';
源码结构:
bash
antd/
├── es/ # ES Module 版本
│ ├── button/
│ │ ├── index.js # 入口文件
│ │ ├── button.js # 主组件
│ │ └── style/ # 样式文件
│ ├── modal/
│ └── ...
├── lib/ # CommonJS 版本
└── dist/ # UMD 版本
2. 组合模式(Composition Pattern)
antd 的 Form 组件是组合模式的典型应用:
javascript
// antd Form 组件使用组合模式
import { Form, Input, Button } from 'antd';
const MyForm = () => (
<Form>
<Form.Item name="username" rules={[{ required: true }]}>
<Input placeholder="用户名" />
</Form.Item>
<Form.Item name="password" rules={[{ required: true }]}>
<Input.Password placeholder="密码" />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
);
源码分析:Form.Item 作为容器,组合了表单控件和验证逻辑。
3. 装饰器模式(Decorator Pattern)
antd 使用高阶组件(HOC)实现装饰器模式:
javascript
// antd 的 withConfigConsumer 高阶组件
import { ConfigConsumer } from '../config-provider/context';
function withConfigConsumer(config) {
return function withConfigConsumerFunc(Component) {
return function WrappedComponent(props) {
return (
<ConfigConsumer>
{context => <Component {...config} {...props} {...context} />}
</ConfigConsumer>
);
};
};
}
// 使用装饰器增强组件
const EnhancedButton = withConfigConsumer({
prefixCls: 'ant-btn'
})(Button);
4. 工厂模式(Factory Pattern)
antd 的 notification 组件使用工厂模式:
javascript
// notification 工厂函数
import Notification from './notification';
// 创建不同类型的通知
const notification = {
success: (config) => Notification.success(config),
error: (config) => Notification.error(config),
info: (config) => Notification.info(config),
warning: (config) => Notification.warning(config),
open: (config) => Notification.open(config),
};
// 使用
notification.success({
message: '操作成功',
description: '数据已保存',
});
五、如何做一个 demo 出来
1. 环境要求
- Node.js 14+
- React 16.8+
- TypeScript(可选)
2. 安装命令
bash
# 创建 React 项目
npx create-react-app antd-pattern-demo --template typescript
# 安装 antd
cd antd-pattern-demo
npm install antd
# 安装分析工具
npm install --save-dev @types/react @types/react-dom
3. 目录结构说明
bash
antd-pattern-demo/
├── src/
│ ├── components/
│ │ ├── MyButton/ # 自定义按钮组件
│ │ ├── MyForm/ # 自定义表单组件
│ │ └── MyModal/ # 自定义弹窗组件
│ ├── patterns/ # 设计模式示例
│ │ ├── composition/ # 组合模式
│ │ ├── decorator/ # 装饰器模式
│ │ └── factory/ # 工厂模式
│ ├── App.tsx
│ └── index.tsx
├── package.json
└── tsconfig.json
4. 最小可运行示例
组合模式示例:
typescript
// src/patterns/composition/FormDemo.tsx
import React from 'react';
import { Form, Input, Button, Select } from 'antd';
const { Option } = Select;
const FormDemo: React.FC = () => {
const onFinish = (values: any) => {
console.log('表单值:', values);
};
return (
<Form
name="basic"
initialValues={{ remember: true }}
onFinish={onFinish}
layout="vertical"
{/* 组合 Input 和验证规则 */}
<Form.Item
label="用户名"
name="username"
rules={[
{ required: true, message: '请输入用户名' },
{ min: 3, message: '至少3个字符' }
]}
<Input placeholder="请输入用户名" />
</Form.Item>
{/* 组合 Select 和选项 */}
<Form.Item
label="角色"
name="role"
rules={[{ required: true, message: '请选择角色' }]}
<Select placeholder="请选择角色">
<Option value="admin">管理员</Option>
<Option value="user">普通用户</Option>
<Option value="guest">访客</Option>
</Select>
</Form.Item>
{/* 组合 Button 和提交逻辑 */}
<Form.Item>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form.Item>
</Form>
);
};
export default FormDemo;
装饰器模式示例:
typescript
// src/patterns/decorator/withLoading.tsx
import React, { ComponentType, useState, useEffect } from 'react';
import { Spin } from 'antd';
// 高阶组件:为组件添加加载状态
function withLoading<P extends object>(
WrappedComponent: ComponentType<P>
): React.FC<P & { isLoading?: boolean }> {
return function WithLoadingComponent(props) {
const [loading, setLoading] = useState(props.isLoading || false);
// 模拟异步加载
useEffect(() => {
if (props.isLoading) {
setLoading(true);
const timer = setTimeout(() => {
setLoading(false);
}, 2000);
return () => clearTimeout(timer);
}
}, [props.isLoading]);
if (loading) {
return (
<div style={{ padding: '50px', textAlign: 'center' }}>
<Spin size="large" />
<div style={{ marginTop: '16px' }}>加载中...</div>
</div>
);
}
return <WrappedComponent {...props as P} />;
};
}
// 使用装饰器
const UserList: React.FC<{ users: string[] }> = ({ users }) => (
<ul>
{users.map((user, index) => (
<li key={index}>{user}</li>
))}
</ul>
);
const UserListWithLoading = withLoading(UserList);
// 在组件中使用
const App: React.FC = () => {
const users = ['张三', '李四', '王五'];
return (
<div>
<h2>用户列表(带加载效果)</h2>
<UserListWithLoading users={users} isLoading={true} />
</div>
);
};
工厂模式示例:
typescript
// src/patterns/factory/NotificationFactory.tsx
import React from 'react';
import { Button, Space } from 'antd';
import { notification } from 'antd';
// 通知工厂
class NotificationFactory {
static create(type: 'success' | 'error' | 'info' | 'warning', config: any) {
const methods = {
success: notification.success,
error: notification.error,
info: notification.info,
warning: notification.warning,
};
return methods[type]({
duration: 3,
placement: 'topRight',
...config,
});
}
// 预定义的通知类型
static success(message: string, description?: string) {
return this.create('success', { message, description });
}
static error(message: string, description?: string) {
return this.create('error', { message, description });
}
static info(message: string, description?: string) {
return this.create('info', { message, description });
}
static warning(message: string, description?: string) {
return this.create('warning', { message, description });
}
}
// 使用工厂
const NotificationDemo: React.FC = () => {
const showNotification = (type: 'success' | 'error' | 'info' | 'warning') => {
const messages = {
success: '操作成功!',
error: '操作失败!',
info: '这是提示信息',
warning: '请注意警告',
};
NotificationFactory[type](messages[type], '详细描述信息');
};
return (
<Space>
<Button type="primary" onClick={() => showNotification('success')}>
成功通知
</Button>
<Button danger onClick={() => showNotification('error')}>
错误通知
</Button>
<Button onClick={() => showNotification('info')}>
信息通知
</Button>
<Button type="dashed" onClick={() => showNotification('warning')}>
警告通知
</Button>
</Space>
);
};
5. 运行项目
bash
# 启动开发服务器
npm start
# 访问 http://localhost:3000
六、设计模式在前端开发中的应用场景
1. 组合模式(Composition)
适用场景:
- 表单组件(Form + Form.Item + Input)
- 布局组件(Layout + Header + Content + Footer)
- 导航菜单(Menu + Menu.Item + SubMenu)
antd 源码示例:
typescript
// antd/es/form/Form.tsx
const Form: React.FC<FormProps> = (props) => {
return (
<FormProvider>
<FormContext.Provider value={formContextValue}>
<FormComponent {...props} />
</FormContext.Provider>
</FormProvider>
);
};
// Form.Item 作为子组件
Form.Item = FormItem;
2. 装饰器模式(Decorator)
适用场景:
- 权限控制(withAuth)
- 数据加载(withLoading)
- 错误处理(withErrorBoundary)
- 样式增强(withStyles)
antd 源码示例:
typescript
// antd/es/config-provider/context.tsx
export const ConfigConsumer = ConfigContext.Consumer;
// 使用 ConfigConsumer 装饰组件
export function withConfigConsumer<C extends React.ComponentType<any>>(
config: ConsumerConfig
) {
return function withConfigConsumerFunc(
Component: C
): React.ComponentType<any> {
// 返回装饰后的组件
return (props: any) => (
<ConfigConsumer>
{(context) => (
<Component {...config} {...props} {...context} />
)}
</ConfigConsumer>
);
};
}
3. 工厂模式(Factory)
适用场景:
- 创建不同类型的弹窗(Modal.success/error/info)
- 创建不同类型的消息(message.success/error)
- 创建不同类型的通知(notification.success/error)
antd 源码示例:
typescript
// antd/es/modal/confirm.tsx
export default function confirm(config: ModalFuncProps) {
// 创建确认对话框的工厂函数
const div = document.createElement('div');
document.body.appendChild(div);
let currentConfig = { ...config, close, visible: true };
function destroy() {
// 销毁逻辑
}
function render(props: any) {
// 渲染逻辑
}
function update(newConfig: ModalFuncProps) {
// 更新逻辑
}
function close() {
// 关闭逻辑
}
render(currentConfig);
return {
destroy: close,
update,
};
}
// 工厂方法
Modal.confirm = (props: ModalFuncProps) => confirm(props);
Modal.success = (props: ModalFuncProps) => confirm({ ...props, icon: <CheckCircleOutlined /> });
Modal.error = (props: ModalFuncProps) => confirm({ ...props, icon: <CloseCircleOutlined /> });
七、性能优化与最佳实践
1. 按需引入(与 lodash-es 同款)
typescript
// 推荐:按需引入
import Button from 'antd/es/button';
import Form from 'antd/es/form';
import 'antd/es/button/style';
import 'antd/es/form/style';
// 不推荐:全量引入
import { Button, Form } from 'antd';
import 'antd/dist/antd.css';
2. 使用 babel-plugin-import
javascript
// .babelrc 或 babel.config.js
{
"plugins": [
["import", {
"libraryName": "antd",
"libraryDirectory": "es",
"style": true
}]
]
}
// 现在可以这样写,插件会自动转换
import { Button } from 'antd';
// 转换为 ↓
import Button from 'antd/es/button';
import 'antd/es/button/style';
3. 组件性能优化
typescript
// 使用 React.memo 避免不必要的重渲染
import React, { memo } from 'react';
import { Button } from 'antd';
const MyButton = memo(({ onClick, children }) => {
console.log('MyButton 渲染');
return <Button onClick={onClick}>{children}</Button>;
});
// 使用 useCallback 缓存函数
const App = () => {
const handleClick = useCallback(() => {
console.log('按钮点击');
}, []);
return <MyButton onClick={handleClick}>点击我</MyButton>;
};
八、与 lodash-es 的对比分析
| 特性 | lodash-es | antd | 共同点 |
|---|---|---|---|
| 模块化 | ES Module 独立文件 | ES Module 独立组件 | 都支持按需引入 |
| Tree Shaking | 支持 | 支持 | 都依赖静态分析 |
| 设计模式 | 函数式编程 | 面向对象设计模式 | 都注重代码组织 |
| 使用场景 | 工具函数 | UI 组件 | 都提供高质量代码 |
核心相似点 :都通过优秀的架构设计,解决了代码复用 和性能优化的问题。
九、常见坑与注意事项
1. 样式问题
typescript
// 错误:忘记引入样式
import { Button } from 'antd';
// 缺少:import 'antd/es/button/style';
// 正确:使用 babel-plugin-import 或手动引入
import Button from 'antd/es/button';
import 'antd/es/button/style';
2. 版本兼容性
json
// package.json
{
"dependencies": {
"antd": "^4.0.0", // 注意主版本号
"react": "^16.8.0", // 需要 React 16.8+
"react-dom": "^16.8.0"
}
}
3. TypeScript 配置
json
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
}
}
4. 自定义主题
javascript
// craco.config.js(Create React App)
const CracoLessPlugin = require('craco-less');
module.exports = {
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: {
'@primary-color': '#1DA57A', // ��改主题色
},
javascriptEnabled: true,
},
},
},
},
],
};
十、总结
antd 和 lodash-es 虽然解决不同问题,但都体现了优秀前端库的共同特点:
- 模块化设计:支持按需引入,减少打包体积
- 设计模式应用:组合、装饰器、工厂等模式提升代码质量
- 性能优化:Tree Shaking、Memoization 等技术
- 开发者体验:清晰的 API、完整的文档、TypeScript 支持
学习建议:
- 阅读优秀开源库的源码,理解设计思想
- 在实际项目中应用设计模式
- 关注性能优化,特别是打包体积
- 保持代码的可维护性和可扩展性
最后:优秀的前端工程师不仅要会使用工具,更要理解工具背后的设计思想。antd 和 lodash-es 都是学习前端架构的绝佳教材。
如果对你有用,欢迎点赞、收藏、关注! 下一篇我们将深入分析 Vue KeepAlive 的源码实现。
参考资料: