修改端口号
根目录下的 .env
文件:
PORT=8888
目录结构 (umijs.org)
新增页面
在 umirc.ts 中进行配置。
新增页面 - Ant Design Pro
这里有一个配置 icon:string
,可以在菜单加 icon 图标,默认使用 antd 的 icon 名,默认不适用二级菜单的 icon,例如:icon:"QuestionCircleOutlined"
。
图标 Icon - Ant Design (antgroup.com)
二级菜单,也就是子路由。需要使用配置项 routes:[{}]
,类似于 vue-router 中的 children。
还有一个配置: hideInMenu:true
可以在菜单中不展示这个路由,包括子路由。例如登录、注册什么的。
menuRender: false
当前路由不展示菜单
代理
也是直接在 umirc.ts 中进行配置。
配置 (umijs.org)
ProComponents
antd pro 内置了 ProComponents。
https://procomponents.ant.design/docs
里面的组件是基于 antd 的二次封装,注意属性及内置方法和 antd 的相同点和差异。比如表格:
https://procomponents.ant.design/components/schema#valuetype-%E5%88%97%E8%A1%A8
表格 Table - Ant Design (antgroup.com)
其中 render 属性类似于插槽,可以在 table 里面插入各种组件。
设置全局 CSS
直接在 src 目录下创建 global.css 的文件,默认被配置为全局样式。目录结构 (umijs.org)
Form 回填数据
antd Form
关于发送请求获取数据
有两种处理方式:
- 通过dispatch一个action到状态仓库,然后状态仓库来发请求,请求回来的数据放入到数据仓库中
- 适用于数据量不多
- 多个组件要共享某一块数据
- 直接在组件里面请求数据
- 数据量很大,在向服务器发送请求的时候,只能分页请求
- 不需要和其他组件共享
说一下 ProTable 里面的 request:
https://procomponents.ant.design/components/table#request
ProTable有一个重要的属性叫做 request ,该属性对应的值一般是一个异步函数,该异步函数自动接受一个params,params中会有默认的当前页码(current)和每一页的条数(pageSiz2e)(当然还会捕获其他参数,可以自己手动log下),这两个值会有默认值,current默认为1,pageSize默认为20,可以通过配置pagination属性来修改current和pageSize的值。
此外,在查询表单查询时和 params
参数发生修改时 request 会重新执行,同时也会触发 onChange 等回调。
<ProTable// params 是需要自带的参数// 这个参数优先级更高,会覆盖查询表单的参数headerTitle="用户列表"columns={columns} // antd table 需要的表头配置rowKey={row => row.id} // 配置表格的行 keypagation={{showQuickJumper: true,showSizeChanger: true,pageSizeOptions: ['10', '20', '30', '40'],...pagation, // 这个参数是自定义的 state 用于响应式改变 current 和 pageSizeonChange: handlePageChange // 自定义分页数据改变的回调 会自动传入两个参数 current 和 pageSize 需要自己手动更新到 state 中}}request={async (// 第一个参数 params 查询表单和 params 参数的结合 必填// 第一个参数中一定会有 pageSize 和 current ,这两个参数是 antd 的规范params,sort,filter,) => {// 这里需要返回一个 Promise,在返回之前你可以进行数据转化// 如果需要转化参数可以在这里进行修改const res = await myQuery({page: params.current,pageSize: params.pageSize,});return {// 返回当前页的数据数组data: res.data.data,// success 请返回 true,// 不然 table 会停止解析数据,即使有数据success: true,// 不传会使用 data 的长度,如果是分页一定要传// 数据总数total: res.data.total,};}}
/>
ref.current.reload(); 可以刷新 ProTable。
Warning:Cannot update a component InternalFormItem)while rendering a different component userForm) 该警告出现的原因,是因为在初次渲染组件的时候,我们设置了数据的回填,导致组件初次还没有渲染完毕,又在更新。如何解决,也非常简单,我们等待第一次渲染完毕后再进行数据的回填,所以我们将回填的代码放入useEffect
粒子动画
登录页面的Canvas动画,使用到的是一个第三方库,叫做 react-canvas-nest
react-canvas-nest - npm (npmjs.com)
配置初始化数据
数据流 (umijs.org)
getInitialState 方法可以配置一些初始化数据,编写 src/app.ts
的导出方法 getInitialState()
,其返回值将成为全局初始状态。
可以在其他组件通过const initialState = useModel('@@initialState');
获取。
以登录功能为例(类似于导航守卫):
export async function getInitialState() {if (location.pathname === '/login') {// 强行进入登录页const token = localStorage.getItem('token');if (token) {const res = await fetch('/api/user/info');if (res.data) {// 说明不仅有 token 而且 token 有效message.error('请先退出后再登录');history.go(-1);}}} else {// 进入其他页面const res = await fetch('/api/user/info');if (res.data) {// 说明不仅有 token 而且 token 有效const {name, avatar} = res.data;return {name, avatar};} else {// 说明没有 token 或者 token 无效 需要重新登录localStorage.removeItem('token');message.error('用户无效,请先登录');location.href = '/login';}}return {name: '@umijs/max'};
}
请求响应拦截器
请求 (umijs.org)
// 配置请求响应拦截器
export const request = {timeout: 3000,requestInterceptors: [function (url, options) {const token = localStorage.getItem('token');if (token) {options.headers['Authorization'] = `Bearer ${token}`;}return {url, options};}],responseInterceptors: [ // 直接写一个 function,作为拦截器(response) => {// 不再需要异步处理读取返回体内容,可直接在data中读出,部分字段可在 config 中找到const {data = {}, config} = response;// do somethingreturn response},// 一个二元组,第一个元素是 request 拦截器,第二个元素是错误处理[(response) => {return response}, (error) => {return Promise.reject(error)}],// 数组,省略错误处理[(response) => {return response}]]
}
退出登录、logo和标题的默认配置
布局与菜单 (umijs.org)
https://procomponents.ant.design/components/layout
export const layout = () => {return {logo: 'https://img.alicdn.com/tfs/TB1YHEpwUT1gK0jSZFhXXaAtVXa-28-27.svg',menu: {locale: false,},logout: () => {localStorage.removeItem('token');location.href = '/login';message.success('退出成功')}};
};
权限管理
权限 (umijs.org)
- 开启配置
umirc.js
中配置access: {},
路由菜单权限
- 在
src/access.ts
提供权限配置
该文件需要默认导出一个方法,导出的方法会在项目初始化时被执行。该方法需要返回一个对象,对象的每一个值就对应定义了一条权限。
export default (initialState) => {// 在这里按照初始化数据定义项目中的权限,统一管理// 参考文档 https://umijs.org/docs/max/access// initialState 是自动传入的 是在 getInitialState 中定义在全局初始化的数据if (initialState) {return {superAdmin: initialState.adminInfo.permission === 1,normalAdmin: initialState.adminInfo.permission === 1 ||initialState.adminInfo.permission === 2,};} else {return {superAdmin: false,normalAdmin: false,}}
};
- 配合路由管理权限
权限 (umijs.org)
这里我自定义了 access 作为区别普通权限和超级权限。
{name: ' 管理员信息',path: '/user/manager',icon: 'TeamOutlined',component: './Manager',access: 'superAdmin',
},
{name: ' 个人信息',path: '/user/personal',icon: 'UserOutlined',component: './Personal',access: 'normalAdmin',
},
自定义权限
对于页面中某一块区域的权限管理,可以使用 useAccess。
import { useAccess } from 'umi';const access = useAccess();
useAccess() 方法可以返回一个对象:
{ superAdmin: false, normalAdmin: false, }
,由此获取该页面(路由)的权限。
<Access>
组件拥有 accessible
和 fallback
两个属性,当 accessible
为 true
时会渲染子组件,当 accessible
为 false
会渲染 fallback
属性对应的 ReactNode
。
<Accessaccessible={access.superAdmin}fallback={<div>Can not read foo content.</div>}
>Foo content.
</Access>
图表
图表 (umijs.org)
所有图表 (ant.design)