在我们学习 Ant Design Pro V5 的时候,我们要简单了解下他是如何调用组件,页面执行顺序等,也是学习这个框架中不可缺少的一环
目录结构
关于目录结构这块,增加公共页面类,存放公共页面类,便于开发~
├── config # umi 配置,包含路由,构建等配置
├── mock # 本地模拟数据
├── public
│ └── favicon.png # Favicon
├── src
│ ├── assets # 本地静态资源
│ ├── commonPages # 公共页面
│ ├── components # 业务通用组件
│ ├── e2e # 集成测试用例
│ ├── layouts # 通用布局
│ ├── models # 全局 dva model
│ ├── pages # 业务页面入口和常用模板
│ ├── services # 后台接口服务
│ ├── utils # 工具库
│ ├── locales # 国际化资源
│ ├── global.less # 全局样式
│ └── global.ts # 全局 JS
├── tests # 测试工具
├── README.md
└── package.json
页面代码结构推荐
这里建议将接口单独分离出来~
src
├── components
└── pages
├── Welcome // 路由组件下不应该再包含其他路由组件,基于这个约定就能清楚的区分路由组件和非路由组件了
| ├── components // 对于复杂的页面可以再自己做更深层次的组织,但建议不要超过三层
| ├── index.tsx // 页面组件的代码
| └── index.less // 页面样式
| └── interface.d.ts // 页面复杂,单独把ts拿出来
| └── services.ts // 接口
| └── mock.ts // 模拟数据,大部分不需要
页面执行顺序
1.首先执行
我们先看看 /scr/app.tsx
这段代码
首先页面打开(无论哪个页面都会执行),会执行 app.tsx
里的 getInitialState
,然后走向queryCurrentUser
这个函数,在这个函数上他会判断 access
是否存在,如果不存在则会报错,发送状态码为401, 然后就会走向登录页面,反之则会停留在当前页面
2.抵达登录页面
到达登录页面后。输入账号密码时走向 fetchUserInfo
这个方法,这个方法主要的作用是存储了一开始登录接口所需的函数
注意,这里进去的页面不会执行 getInitialState
这个函数,所以再次要执行获取用户信息的方法
3.页面切换
我们做的页面会放在浏览器上,我们需要登录信息才能够打开,但由于许多外部原因会导致存储的信息发生变化,如清储缓存,时间过长导致登录信息失效等,那么在 V5 中如何判断的呢?
会将登录信息放在 initialState 中,我们需要在 app,tsx
中的 onPageChange
这个方法里
这个方法是通过页面转换而触发的,在这里也会判断用户信息是否存在,如果不存在,则会重新跳转登录界面
UI设置
1、@ 做了什么
我们随意的可以看见类似这样的引入
import Footer from '@/components/Footer';
那么 @是干嘛的呢?
其实在项目中引入分为绝对路径和相对路径,我们通常将组件放置在 component
模块下,配置放置在 utils
模块下,那么 @ 实际上就是 相当于绝对路径 也就是 /src 的作用,他就是别名
帮助我更快速的引入,详细的可参考 webpack别名设置
2、简单的数据流
中后台场景下,绝大多数页面的数据流转都是在当前页完成,在页面挂载的时候请求后端接口获取并消费,这种场景下并不需要复杂的数据流方案。但是也存在需要全局共享的数据,如用户的角色权限信息或者其他一些页面间共享的数据。那么怎么才能缓存并支持在多个页面直接去共享这部分数据呢。简而言之,就是状态管理
状态管理相信大家首先想到的 redux
,其次是 mobx
,那么在Ant Design Pro 中用了什么来更好的管理状态呢?
在 V4 的版本中主推的 dva
数据流,这里就不详细介绍了
那么在 V5 中呢?毫无疑问,官方设置的更加简便,相对于 redux、mobx、dva那简直简单的太多了,相对于是傻瓜式操作~
import { useModel } from 'umi';
const { initialState, setInitialState } = useModel('@@initialState');
只需要 引入 useModel
就可以进行使用了
initialState
: 数据setInitialState
: 设置数据
优化配置
我们不难发现 initialState
是整个项目的灵魂,他是初始化的数据,为了简便,我们把他提取出来,从而更改全局的配置
位置: /src/utils/initData
之后所有的操作都可以放到这个文件去做初始化数据,他返回的对象就是 useModel('@@initialState')
里的值
/**
* @module 初始化方法
*/
const initData = async () => {
const currentUser = await queryCurrentUser()
// 动态路由:menuData接收的为路由的函数,为false时,不启动动态路由
// const menuData: MenuDataItem[] = await getMenuData()
return {
currentUser: currentUser,
content: content,
// menuData: formatter(menuData), // 示例,动态路由
menuData: false,
domesy:{
layoutSy,
pageLayoutSy,
tableSy,
fromSy,
maskSy,
CardSy,
storageSy,
OssUpLoadSy,
}
}
}
另外我在原有的基础上设置了一些简便的方法,后续会讲到~