项目实战 - Ant Design


本站和网页 https://ant.design/docs/react/practical-projects-cn 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

项目实战 - Ant Design
Enable JavaScript to run this app.
Ant Design⌘ K设计研发组件博客资源5.2.1更多中EnAnt Design of React快速上手项目实战在 create-react-app 中使用在 TypeScript 中使用样式兼容定制主题使用自定义日期库从 v4 到 v5社区精选组件国际化FAQ贡献指南更新日志初始化项目新建路由实现 Product UI 组件准备 Mock 数据完成 products 页ProLayout构建应用下一步项目实战快速上手在 create-react-app 中使用相关资源Ant Design ChartsAnt Design ProAnt Design Pro ComponentsAnt Design MobileAnt Design MiniAnt Design Landing-首页模板集Scaffolds-脚手架市场Umi-React 应用开发框架dumi-组件/文档研发工具qiankun-微前端框架ahooks-React Hooks 库Ant Motion-设计动效国内镜像站点 🇨🇳社区Awesome Ant DesignMediumTwitterAnt Design 语雀专栏Ant Design 知乎专栏体验科技专栏SEE Conf-蚂蚁体验科技大会加入我们帮助GitHub更新日志常见问题报告 Bug议题讨论区StackOverflowSegmentFault更多产品语雀-构建你的数字花园AntV-数据可视化解决方案Egg-企业级 Node.js 框架Kitchen-Sketch 工具集蚂蚁体验科技主题编辑器Made with ❤ by蚂蚁集团和 Ant Design 开源社区在真实项目开发中,除了 Ant Design 这样的 UI 库,你可能会还会需要构建工具、路由方案、CSS 方案、数据流方案、请求库和请求方案、国际化方案、权限方案、Icons 方案,等等,才能完成一个完整的项目。我们基于业务场景的场景,推出了基于 React 的企业级应用框架 Umi,推荐你在项目中使用。Umi,中文发音为「乌米」,是可扩展的企业级前端应用框架,也是蚂蚁集团的底层前端框架,已直接或间接地服务了 10000+ 应用。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。本文会引导你使用 Umi、Ant Design 和 Ant Design Pro 从 0 开始创建一个简单应用。初始化项目推荐使用 pnpm 创建 Umi 脚手架,执行以下命令。$ mkdir myapp && cd myapp$ pnpm create umi如果你使用 npm,可执行  npm create umi,效果一致;如果你使用 yarn,可执行  yarn create umi,效果也一致;如果你使用 bun,那说明你是个非常潮的人,可执行 bunx create-umi(注意,create 和 umi 之间有个 -)。这里选「Simple App」,因为我们要从 “0” 开始。? Pick Umi App Template › - Use arrow-keys. Return to submit.❯ Simple App Ant Design Pro Vue Simple App这里建议选「pnpm」,pnpm 在速度以及处理幽灵依赖方面都更有优势。? Pick Npm Client › - Use arrow-keys. Return to submit. npm cnpm tnpm yarn❯ pnpm这里国内的朋友建议选「taobao」,否则选「npm」。选择 npm taobao 源在安装依赖时通常会更快一些。? Pick Npm Registry › - Use arrow-keys. Return to submit. npm❯ taobao然后工具会自动安装依赖,并执行 umi 的初始化脚本。在启动项目之前,我们再安装一些本教程会用到的依赖。$ pnpm i @umijs/plugins -D$ pnpm i antd axios @ant-design/pro-layout -S其中 @umijs/plugins 是 Umi 的官方插件集,包含了 valtio、react-query、styled-components、locale、access、qiankun 等大量插件,可让用户通过配置的方式一键开启和使用;antd 就不用介绍了;axios 是请求库;@ant-design/pro-layout 是用于生成中后台布局的组件。(这里将运行时依赖和编译时依赖分别保存到 dependencies 和 devDependencies,是目前社区推荐的方式)完成后,执行以下命令启动项目。$ npm run devumi devinfo - Umi v4.0.46 ╔════════════════════════════════════════════════════╗ ║ App listening at: ║ ║ > Local: http://localhost:8000 ║ready - ║ > Network: http://*********:8000 ║ ║ ║ ║ Now you can open browser with the above addresses↑ ║ ╚════════════════════════════════════════════════════╝跟着提示点击命令行里的 Url,会自动打开浏览器。如果顺利,你会看到如下界面。新建路由我们要写个应用来先显示产品列表。首先第一步是创建路由,路由可以想象成是组成应用的不同页面。Umi 用户通常不需要关心 Umi 背后的实现,但如果你想知道,Umi 的路由是基于 [email protected] 实现(注:不是最新的 6.4,6.4 包含的 loader 和 action 功能并不是 Umi 所需要的)。我们通过命令即可创建路由。$ npx umi g page productsWrite: src/pages/products.tsxWrite: src/pages/products.less然后修改配置文件 .umirc.ts 加上新增的路由声明。import { defineConfig } from "umi";
export default defineConfig({ routes: [ { path: "/", component: "index" }, { path: "/docs", component: "docs" },+ { path: "/products", component: "products" }, ], npmClient: "pnpm",});由于脚手架默认使用的是配置式路由,顾名思义,就是路由是自己一行行配出来的,虽然繁琐,但灵活性更高,这种方式需要在配置里加上 routes 字段,详见 Umi 文档之路由。此外,Umi 还支持约定式路由,意思是文件系统即路由,所以无需配置路由即可生效。然后我们编辑下 src/layouts/index.tsx 文件,在全局布局路由里加上到 /products 路径的导航。<li> <Link to="/docs">Docs</Link></li>+ <li>+ <Link to="/products">Products</Link>+ </li>打开 http://localhost:8000/products ,如果顺利,你会看到如下页面。实现 Product UI 组件随着应用的发展,你会需要在多个页面分享 UI 元素 (或在一个页面使用多次),在 Umi 里你可以把这部分抽成 component 。我们来编写一个 ProductList component,这样就能在不同的地方显示产品列表了。新建 src/components/ProductList.tsx 文件,内容如下。import { Button, Popconfirm, Table } from 'antd';import React from 'react';
const ProductList: React.FC<{ products: { name: string }[]; onDelete: (id: string) => void }> = ({ onDelete, products,}) => { const columns = [ { title: 'Name', dataIndex: 'name', }, { title: 'Actions', render(text, record) { return ( <Popconfirm title="Delete?" onConfirm={() => onDelete(record.id)}> <Button>Delete</Button> </Popconfirm> ); }, }, ]; return <Table rowKey="id" dataSource={products} columns={columns} />;};
export default ProductList;准备 Mock 数据假设我们已经和后端约定好了 API 接口,那现在就可以使用 Mock 数据来在本地模拟出 API 应该要返回的数据,这样一来前后端开发就可以同时进行,不会因为后端 API 还在开发而导致前端的工作被阻塞。Umi 提供了开箱即用的 Mock 功能,能够用方便简单的方式来完成 Mock 数据的设置。创建 mock 目录,并在此目录下新增 products.ts 文件,内容如下。import { defineMock } from 'umi';
type Product = { id: string; name: string;};
let products: Product[] = [ { id: '1', name: 'Umi' }, { id: '2', name: 'Ant Design' }, { id: '3', name: 'Ant Design Pro' }, { id: '4', name: 'Dva' },];
export default defineMock({ 'GET /api/products': (_, res) => { res.send({ status: 'ok', data: products, }); }, 'DELETE /api/products/:id': (req, res) => { products = products.filter((item) => item.id !== req.params.id); res.send({ status: 'ok' }); },});然后访问 http://localhost:8000/api/products ,就能看到接口响应结果了。完成 products 页完成了 UI 组件和 Mock 数据,是时候把他们结合到一起了。这里需要用到请求方案,我们在这里的选择是 react-query(如果你想说 @tanstack/react-query,没错,他们是同一个库,@tanstack/react-query 是 react-query 改名后的包)。所以在开始之前,需要修改配置启用一键启用 Umi 的 react-query 插件。先编辑 .umirc.ts,由于有探测到不能热更的配置项变更,配置文件保存后 umi dev 的 server 会自动重启。import { defineConfig } from "umi";
export default defineConfig({+ plugins: ['@umijs/plugins/dist/react-query'],+ reactQuery: {}, routes: [ { path: "/", component: "index" }, { path: "/docs", component: "docs" }, { path: "/products", component: "products" }, ], npmClient: 'pnpm',});再编辑 src/pages/products.tsx,内容如下。import ProductList from '@/components/ProductList';import axios from 'axios';import React from 'react';import { useMutation, useQuery, useQueryClient } from 'umi';import styles from './products.less';
export default function Page() { const queryClient = useQueryClient(); const productsQuery = useQuery(['products'], { queryFn() { return axios.get('/api/products').then((res) => res.data); }, }); const productsDeleteMutation = useMutation({ mutationFn(id: string) { return axios.delete(`/api/products/${id}`); }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['products'] }); }, }); if (productsQuery.isLoading) return null; return ( <div> <h1 className={styles.title}>Page products</h1> <ProductList products={productsQuery.data.data} onDelete={(id) => { productsDeleteMutation.mutate(id); }} /> </div> );}这里,我们通过 useQuery() 拉取来自 /api/products 的数据,然后在 onDelete 事件里通过 useMutation() 提交 DELETE 请求到 /api/products/${id} 进行删除操作。关于 react-query 的详细使用,可参考 Umi 插件之 React Query 和 React Query 官网。保存后,你应该会看到如下界面。ProLayout一个标准的中后台页面,一般都需要一个布局,这个布局很多时候都是高度雷同的,ProLayout 封装了常用的菜单,面包屑,页头等功能,提供了一个不依赖的框架且开箱即用的高级布局组件。并且支持  side, mix, top  三种模式,更是内置了菜单选中,菜单生成面包屑,自动设置页面标题的逻辑。先修改配置,为每个路由新增 name 字段,用于给 ProLayout 做菜单渲染使用。import { defineConfig } from "umi";
export default defineConfig({ routes: [- { path: "/", component: "index" },+ { path: "/", component: "index", name: "home" },- { path: "/docs", component: "docs" },+ { path: "/docs", component: "docs", name: "docs" },- { path: "/products", component: "products" },+ { path: "/products", component: "products", name: "products" }, ], plugins: ["@umijs/plugins/dist/react-query"], reactQuery: {}, npmClient: "pnpm",});编辑 src/layouts/index.tsx,内容如下。import { ProLayout } from '@ant-design/pro-layout';import { Link, Outlet, useAppData, useLocation } from 'umi';
export default function Layout() { const { clientRoutes } = useAppData(); const location = useLocation(); return ( <ProLayout route={clientRoutes[0]} location={location} title={'Umi x Ant Design'} menuItemRender={(menuItemProps, defaultDom) => { if (menuItemProps.isUrl || menuItemProps.children) { return defaultDom; } if (menuItemProps.path && location.pathname !== menuItemProps.path) { return ( <Link to={menuItemProps.path} target={menuItemProps.target}> {defaultDom} </Link> ); } return defaultDom; }} > <Outlet /> </ProLayout> );}这里先用 umi 的 useAppData 拿到全局客户端路由 clientRoutes,这是一份嵌套结构的路由表,我们把 clientRoutes[0] 传给 ProLayout;再通过 useLocation() 拿到 location 信息,也传给 ProLayout 来决定哪个菜单应该高亮;同时我们希望点击菜单时做路由跳转,需要需要定制 ProLayout 的 menuItemRender 方法。聪明的你可能已经发现 src/layouts/index.less 已经没地方引用他了,为了保持项目文件的整洁,可以选择删掉他。此时浏览器会自动刷新,如果顺利,你会看到如下界面。构建应用完成开发并且在开发环境验证之后,就需要部署给我们的用户了,执行以下命令。$ npm run buildinfo - Umi v4.0.46✔ Webpack Compiled successfully in 5.31sinfo - File sizes after gzip: 122.45 kB dist/umi.js 575 B dist/src__pages__products.async.js 312 B dist/src__pages__index.async.js 291 B dist/layouts__index.async.js 100 B dist/layouts__index.chunk.css 55 B dist/src__pages__products.chunk.cssevent - Build index.html构建会打包所有的资源,包含 JavaScript, CSS, Web Fonts, 图片, Html 等。你可以在  dist/  目录下找到这些文件。下一步我们已经完成了一个简单应用,你可能还有很多疑问,比如:如何统一处理出错?如何处理更多路由,比如动态路由,嵌套路由,权限路由等?如何使用数据流方案?如何修改 webpack 配置或切换到 vite 构建模式?等等你可以:访问  Umi 官网了解  Umi 的路由了解比 Umi 集成度更高的  Umi Max了解开箱即用的中后台脚手架  Ant Design Pro了解高级布局  ProLayout了解高级表格  ProTable