开发者:蚂蚁【支付宝,蚂蚁金融】基于React 研发可插拔的企业级 react 应用框架。
通过约定、自动生成和解析代码等方式来辅助开发,减少我们开发者的代码量。
路由做到按需加载
github https://github.com/ant-design/ant-design-pro
https://github.com/sorrycc/blog/issues/66
https://zhuanlan.zhihu.com/p/142412204
Ant Design Pro 使用 Umi 作为开发工具,建议你先查看 Umi 的常见问题
# umijs 4x
yarn create umi my-app
# umijs 3x
yarn create @umijs/umi-app
antd pro5x
https://github.com/ant-design/ant-design-pro/tree/v5.2.0
https://v5-pro.ant.design/zh-CN/docs/folder
https://github.com/websemantics/awesome-ant-design
集成的技术点
集成了 pro-layout 组件
antd pro4x
antd pro4x 常见问题 https://v4-pro.ant.design/docs/faq-cn
antd pro4x文档 https://v4-pro.ant.design/docs/available-script-cn
npx umi block add UserRegister --path=/user/user-register
umi3 可以用 js,把 .umirc.tsx直接改为 .umirc.js, pages下的 ts修改为 js
官方默认生成 ts项目,给人错觉不能使用 js开发
.umirc.js 配置
项目开发,不要修改 pages/.umi目录
$id.js 动态路由 /:id,umi2
[id].js umi3动态路由
umi3 手动新增文件,要把 .umirc.js的里面的 routes给注释掉
create page
create umi
create page index.js
会自动添加到路由,直接新建的目录,需要自己手动添加到路由
npx umi g page index 生成 index.js index.css
src/pages/index.js
src/pages/index.css
npx umi g page class/index
src/pages/class/index.js
src/pages/class/index.css
创建 umi项目
- 请在空文件夹中使用,或者使用 yarn create umi myapp ```jsx npm create umi myapp 选择 ant-design-pro 选择 V5
npm install
npm start # localhost:8000
npm run umi # 区块布局
umi的mock 是对 express的封装
<a name="k0zMV"></a>
## umi block list
[https://github.com/ant-design/pro-blocks](https://github.com/ant-design/pro-blocks)<br />[pro-blocks-master.zip](https://www.yuque.com/attachments/yuque/0/2020/zip/112859/1606634535226-2e00eb7c-504b-4abc-89fb-1d1b03631b3f.zip?_lake_card=%7B%22src%22%3A%22https%3A%2F%2Fwww.yuque.com%2Fattachments%2Fyuque%2F0%2F2020%2Fzip%2F112859%2F1606634535226-2e00eb7c-504b-4abc-89fb-1d1b03631b3f.zip%22%2C%22name%22%3A%22pro-blocks-master.zip%22%2C%22size%22%3A2715331%2C%22ext%22%3A%22zip%22%2C%22source%22%3A%22%22%2C%22status%22%3A%22done%22%2C%22download%22%3Atrue%2C%22type%22%3A%22application%2Fzip%22%2C%22mode%22%3A%22title%22%2C%22uid%22%3A%221606634534186-0%22%2C%22progress%22%3A%7B%22percent%22%3A99%7D%2C%22percent%22%3A0%2C%22id%22%3A%22aV3wK%22%2C%22card%22%3A%22file%22%7D)
umi block add 报错<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/112859/1606634606313-a883095a-bb72-4f65-82ff-144e8bba04f2.png#averageHue=%233c3e48&height=289&id=Cx09t&originHeight=578&originWidth=2192&originalType=binary&ratio=1&rotation=0&showTitle=false&size=764660&status=done&style=none&title=&width=1096)<br />默认仓库数 gitee.com,下载需要登录,解决方法:
1. 进入 /Users/lulongwen/.umi3/blocks/github.com/umijs/umi-blocks/,查看 git remote
```bash
git remote -v
origin https://gitee.com/umijs/umi-blocks.git (fetch)
origin https://gitee.com/umijs/umi-blocks.git (push)
# 修改 git remote
git remote set-url origin https://github.com/ant-design/pro-blocks.git
缺点:下载速度慢些
- 下载 https://github.com/ant-design/pro-blocks 直接把模板移动到 /Users/lulongwen/.umi3/blocks/github.com/umijs/umi-blocks/ 目录就好了
model数据流
umijs@4.x,内置了一套和 hox 一模一样的数据流方案,特点
- 采用约定式目录结构,不用专门写 createStore ,而是自动帮我们引入了所有 model 目录下的 hooks,并注册。
- 在页面中则是通过统一的 useModel,通过其自动生成的 namespace 引用,比如 useModel(‘product’)。
- 这也导致了依赖不明确的问题,umi4 还特地通过编写插件的方式解决跳转问题。
- useModel(‘product’) 必须要通过装插件才能点击跳转
- 必须要在 umijs@4.x 体系下才能使用,无法快速复制迁移到其它的框架下使用
blockConfig
genBlockConfig.js https://github.com/ant-design/pro-blocks
const fs = require('fs');
const { join } = require('path');
const gitUrl = 'https://github.com/ant-design/pro-blocks';
const menuData = {
home: '首页',
Empty: '空白',
login: '登录',
register: '注册',
'register/result': '注册结果',
dashboard: 'Dashboard',
'dashboard/analysis': '分析页',
'dashboard/monitor': '监控页',
'dashboard/workplace': '工作台',
'exception/403': '403',
'exception/404': '404',
'exception/500': '500',
form: '表单页',
'user/login': '登录页',
'user/register': '注册页',
'user/register/result': '注册结果页',
'form/basic/form': '基础表单',
'form/step/form': '分步表单',
'form/advanced/form': '高级表单',
list: '列表页',
'list/table/list': '查询表格',
'list/basic/list': '标准列表',
'list/card/list': '卡片列表',
'list/search': '搜索列表',
'list/search/articles': '搜索列表(文章)',
'list/search/projects': '搜索列表(项目)',
'list/search/applications': '搜索列表(应用)',
profile: '详情页',
'profile/basic': '基础详情页',
'profile/advanced': '高级详情页',
result: '结果页',
'result/success': '成功页',
'result/fail': '失败页',
exception: '异常页',
'exception/not-permission': '403',
'exception/not-find': '404',
'exception/server-error': '500',
'exception/trigger': '触发错误',
account: '个人页',
'account/center': '个人中心',
'account/settings': '个人设置',
'account/trigger': '触发报错',
'account/logout': '退出登录',
editor: '图形编辑器',
'editor/flow': '流程编辑器',
'editor/mind': '脑图编辑器',
'editor/koni': '拓扑编辑器',
};
const tagsKey = {
list: '列表',
search: '搜索',
articles: 'remove',
table: '表格',
form: '表单',
step: 'remove',
basic: '基本',
card: 'remove',
applications: 'remove',
projects: 'remove',
404: 'remove',
403: 'remove',
500: 'remove',
profile: '详情',
advanced: '高级',
result: '结果',
fail: 'remove',
success: 'remove',
user: '用户',
login: '登录',
register: '注册',
account: 'remove',
center: '个人中心',
settings: '个人设置',
dashboard: 'dashboard',
analysis: 'remove',
monitor: 'remove',
workplace: 'remove',
editor: '图形编辑',
flow: 'remove',
koni: 'remove',
mind: 'remove',
exception: '异常',
};
/**
* 从文件数组映射为 pro 的路由
* @param {*} name
*/
const genBlockName = (name) =>
name
.match(/[A-Z]?[a-z]+|[0-9]+/g)
.map((p) => p.toLowerCase())
.join('/');
/**
* 从文件数组映射为 tags 列表
* @param {*} name
*/
const genBlockTags = (name) =>
Array.from(new Set(name.match(/[A-Z]?[a-z]+|[0-9]+/g).map((p) => p.toLowerCase())))
.map((key) => tagsKey[key] || key)
.filter((key) => key !== 'remove');
const getFeature = (filePath) => {
const feature = ['antd'];
const srcPath = join(filePath, 'src');
const localesPath = join(srcPath, 'locales');
if (fs.existsSync(localesPath)) {
feature.push('i18n');
}
const modalTsxPath = join(srcPath, 'model.tsx');
const modalTsPath = join(srcPath, 'model.ts');
const modalJsPath = join(srcPath, 'model.js');
const modalJsxPath = join(srcPath, 'model.jsx');
if (
fs.existsSync(modalTsxPath) ||
fs.existsSync(modalTsPath) ||
fs.existsSync(modalJsPath) ||
fs.existsSync(modalJsxPath)
) {
feature.push('dva');
}
return feature;
};
/**
* 遍历文件地址
* @param path
*/
const getFolderTreeData = (filePath) => {
const files = fs.readdirSync(filePath);
const blockList = files
.map((fileName) => {
const status = fs.statSync(join(filePath, fileName));
if (status.isDirectory() && fileName.indexOf('.') !== 0 && fileName !== 'EmptyPage') {
const absPkgPath = join(filePath, fileName, 'package.json');
if (fs.existsSync(absPkgPath)) {
const pkg = require(absPkgPath);
return {
name: menuData[genBlockName(fileName)],
key: fileName,
description: pkg.description,
url: `${gitUrl}/tree/master/${fileName}`,
path: fileName,
features: getFeature(join(filePath, fileName)),
img: `https://raw.githubusercontent.com/ant-design/pro-blocks/master/${fileName}/snapshot.png?raw=true`,
tags: genBlockTags(fileName),
previewUrl: `https://preview.pro.ant.design/${genBlockName(fileName)}`,
};
}
}
return undefined;
})
.filter((obj) => obj);
blockList.unshift({
key: 'EmptyPage',
name: '空白页面',
description: '一个空白的页面,一切都从这里开始!',
url: 'https://github.com/ant-design/pro-blocks/tree/master/EmptyPage',
path: 'NewPage',
features: ['antd'],
img:
'https://raw.githubusercontent.com/ant-design/pro-blocks/master/EmptyPage/snapshot.png?raw=true',
tags: ['空白页'],
previewUrl: 'https://preview.pro.ant.design',
});
return blockList;
};
fs.writeFileSync(
join(__dirname, '..', 'umi-block.json'),
JSON.stringify({ list: getFolderTreeData(join(__dirname, '../')) }, null, 2),
);