Ant Design:企业级 UI 设计语言与 React 组件库
Ant Design
项目描述
Ant Design 是一套企业级的 UI 设计语言和 React 组件库,致力于提供高质量的设计规范和丰富的组件资源。该项目基于 TypeScript 开发,提供完整的类型定义,支持 React 16 到 19 版本,具有出色的国际化能力和可定制化主题功能。
功能特性
- 丰富的组件库:提供超过 60 个高质量 React 组件,涵盖布局、导航、数据录入、数据展示、反馈等各类场景
- TypeScript 支持:完整的 TypeScript 类型定义,提供优秀的开发体验
- 国际化解决方案:内置多语言支持,轻松实现国际化需求
- 可定制主题:支持 CSS 变量和设计令牌,方便进行主题定制
- 企业级设计规范:遵循 Ant Design 设计语言,保证设计的一致性和专业性
- 跨平台兼容:支持服务端渲染,兼容现代浏览器
- 开发工具完善:提供完整的开发、构建、测试工具链
安装指南
环境要求
- Node.js 版本 >= 16
- React 16 ~ 19
- 现代浏览器支持(Chrome 80+)
安装依赖
# 使用 npm 安装
npm install antd
# 使用 yarn 安装
yarn add antd
# 使用 pnpm 安装
pnpm add antd
# 使用 Bun 安装
bun add antd
开发环境设置
# 克隆项目
git clone https://github.com/ant-design/ant-design.git
# 安装依赖
npm install
# 启动开发服务器
npm start
# 运行测试
npm test
# 构建项目
npm run build
使用说明
基础使用
import React from 'react';
import { Button, DatePicker } from 'antd';
const App = () => (
<>
<Button type="primary">主要按钮</Button>
<DatePicker />
</>
);
export default App;
国际化配置
import React from 'react';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/locale/zh_CN';
const App = () => (
<ConfigProvider locale={zhCN}>
<YourApp />
</ConfigProvider>
);
主题定制
import React from 'react';
import { ConfigProvider } from 'antd';
const theme = {
token: {
colorPrimary: '#00b96b',
},
};
const App = () => (
<ConfigProvider theme={theme}>
<YourApp />
</ConfigProvider>
);
核心代码
组件样式管理
// components/style/index.ts
function pascalCase(name) {
return name.charAt(0).toUpperCase() + name.slice(1).replace(/-(\w)/g, (m, n) => n.toUpperCase());
}
// 自动导入组件样式
const req = require.context('./components', true, /^\.\/[^_][\w-]+\/style\/index\.tsx?$/);
req.keys().forEach((mod) => {
let v = req(mod);
if (v?.default) {
v = v.default;
}
const match = mod.match(/^\.\/([^_][\w-]+)\/index\.tsx?$/);
if (match?.[1]) {
if (match[1] === 'message' || match[1] === 'notification') {
exports[match[1]] = v;
} else {
exports[pascalCase(match[1])] = v;
}
}
});
构建配置
// scripts/dist.config.js
function addLocales(config) {
const newConfig = { ...config };
let packageName = 'antd-with-locales';
if (newConfig.entry['antd.min']) {
packageName += '.min';
}
newConfig.entry[packageName] = './index-with-locales.js';
newConfig.output.filename = '[name].js';
return newConfig;
}
function externalDayjs(config) {
const newConfig = { ...config };
newConfig.externals.dayjs = {
root: 'dayjs',
commonjs2: 'dayjs',
commonjs: 'dayjs',
amd: 'dayjs',
};
return newConfig;
}
图标系统
// site/theme/common/IconSearch/index.tsx
import React, { useCallback, useMemo, useState } from 'react';
import Icon, * as AntdIcons from '@ant-design/icons';
export enum ThemeType {
Filled = 'Filled',
Outlined = 'Outlined',
TwoTone = 'TwoTone',
}
const IconSearch: React.FC = () => {
const [displayState, setDisplayState] = useState({
searchKey: '',
theme: ThemeType.Outlined,
});
const handleSearchIcon = debounce((e: React.ChangeEvent<HTMLInputElement>) => {
setDisplayState(prevState => ({ ...prevState, searchKey: e.target.value }));
}, 300);
const handleChangeTheme = useCallback((value: ThemeType) => {
setDisplayState(prevState => ({ ...prevState, theme: value }));
}, []);
return (
<div>
{/* 图标搜索和展示逻辑 */}
</div>
);
};
演示组件包装器
// site/theme/common/DemoWrapper.tsx
import React, { Suspense } from 'react';
import { DumiDemo, DumiDemoGrid } from 'dumi';
const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
const { showDebug, setShowDebug } = React.useContext(DemoContext);
const [expandAll, setExpandAll] = useLayoutState(false);
const [enableCssVar, setEnableCssVar] = useLayoutState(true);
const demos = React.useMemo(() =>
items.reduce((acc, item) => {
const { debug } = item.previewerProps;
if (debug && !showDebug) return acc;
return acc.concat({
...item,
previewerProps: {
...item.previewerProps,
expand: expandAll,
debug: false,
originDebug: debug,
},
});
}, []),
[expandAll, showDebug]
);
return (
<div className="demo-wrapper">
<ConfigProvider theme={{ cssVar: enableCssVar, hashed: !enableCssVar }}>
<DumiDemoGrid
items={demos}
demoRender={(item) => (
<Suspense key={item.demo.id} fallback={<DemoFallback />}>
<DumiDemo {...item} />
</Suspense>
)}
/>
</ConfigProvider>
</div>
);
};
主题切换动画
// site/theme/common/hooks/useThemeAnimation.ts
const useThemeAnimation = () => {
const {
token: { colorBgElevated },
} = theme.useToken();
const toggleAnimationTheme = (event: React.MouseEvent<HTMLElement>, isDark: boolean) => {
if (!(event && typeof document.startViewTransition === 'function')) return;
const x = event.clientX;
const y = event.clientY;
const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y));
document.startViewTransition(async () => {
// 等待主题变更完成
while (colorBgElevated === animateRef.current.colorBgElevated) {
await new Promise<void>(resolve => setTimeout(resolve, 1000 / 60));
}
const root = document.documentElement;
root.classList.remove(isDark ? 'dark' : 'light');
root.classList.add(isDark ? 'light' : 'dark');
});
};
return toggleAnimationTheme;
};
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码
公众号二维码