【Umi Max】 Ant Design Pro 快速上手

搭建 Umi Max 项目

Umi Max 快速开始

修改端口号

根目录下的 .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 的相同点和差异。比如表格:

表格

表格 Table - Ant Design (antgroup.com)

其中 render 属性(默认以字符串的形式渲染,该函数可以改变渲染逻辑)类似于插槽,可以在 table 里面插入各种组件。

render: (_, record) => (
      <Space>
        {record.labels.map(({ name, color }) => (
          <Tag color={color} key={name}>
            {name}
          </Tag>
        ))}
      </Space>
    ),

_ 表示一个单元格(ReactNode),record 表示该单元格所在的行(也就是渲染该行的数据),原本的字符串可以更改为上面所示的 <Space / > 组件渲染。

高级表格的字段解释:

  • 通过 coloum 定义表格有哪些列
  • ProColumns<GithubIssueItem>[] 属性:
    • dataIndex 对应返回数据对象的字段(id,userAccount,gender…)
    • title 表格列名
    • copyable 是否允许赋值
    • ellipsis 是否允许缩略
    • valueType 声明列的类型
    • valueEnum 字段数据枚举(数据映射,比如 1 -> 男 0 -> 女 等)

高级表格的属性解释:

  • request 封装的请求函数(请求、分类、筛选等功能)

设置全局 CSS

直接在 src 目录下创建 global.css 的文件,默认被配置为全局样式。目录结构 (umijs.org)

Form 回填数据

antd Form

image.png

关于发送请求获取数据

有两种处理方式:

  • 通过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}  // 配置表格的行 key
    pagation={{
        showQuickJumper: true,
        showSizeChanger: true,
        pageSizeOptions: ['10', '20', '30', '40'],
        ...pagation, // 这个参数是自定义的 state 用于响应式改变 current 和 pageSize
        onChange: 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 something
            return 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)

  1. 开启配置 umirc.js 中配置 access: {},

路由菜单权限

  1. 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,
        }
    }
};
  1. 配合路由管理权限

权限 (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> 组件拥有 accessiblefallback 两个属性,当 accessibletrue 时会渲染子组件,当 accessiblefalse 会渲染 fallback 属性对应的 ReactNode

<Access
    accessible={access.superAdmin}
    fallback={<div>Can not read foo content.</div>}
>
    Foo content.
</Access>

图表

图表 (umijs.org)

所有图表 (ant.design)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秀秀_heo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值