在 Ant Design Pro 中,一个完整的前端 UI 交互到服务端处理流程是这样的:

  1. UI 组件交互操作;
  2. 调用 model 的 effect;
  3. 调用统一管理的 service 请求函数;
  4. 使用封装的 request.ts 发送请求;
  5. 获取服务端返回;
  6. 然后调用 reducer 改变 state;
  7. 更新 model。

1.直接发送请求得交互

适用于单页面得交互

1.1配置路由和国际化

  1. //config/routes.ts
  2. {
  3. path:"/person",
  4. icon:"UserOutlined",
  5. name:'person',
  6. component:'./Person'
  7. },
  1. //locales/zh-CN/menu.ts
  2. 'menu.person':'个人中心'

1.2配置mock数据

  1. //mock/person.ts
  2. export default {
  3. '/api/person': [
  4. {id:1,name:'tom',age:22,sex:'男'},
  5. {id:2,name:'jack',age:16,sex:'男'},
  6. {id:3,name:'aswe',age:20,sex:'女'},
  7. {id:4,name:'sary',age:21,sex:'女'},
  8. ]
  9. }

1.3sevice发送请求获取数据

  1. //src/service/person.ts
  2. import request from '@/utils/request';
  3. export async function getPersonDatas() {
  4. return request('/api/person');
  5. }

1.4组件中使用

  1. //src/pages/Person/index.tsx
  2. import React, { useRef } from 'react';
  3. import { PageHeaderWrapper } from '@ant-design/pro-layout';
  4. import { PlusOutlined } from '@ant-design/icons';
  5. import { Button} from 'antd';
  6. import type { ActionType } from '@ant-design/pro-table';
  7. import ProTable from '@ant-design/pro-table';
  8. import { getPersonDatas} from "../../services/person"
  9. const columns = [
  10. {
  11. title:'姓名',
  12. dataIndex: 'name',
  13. },
  14. {
  15. title:'年龄',
  16. dataIndex: 'age',
  17. //不开启搜索
  18. hideInSearch:true
  19. },
  20. {
  21. title:'性别',
  22. dataIndex: 'sex',
  23. hideInSearch:true
  24. },
  25. ];
  26. //获取数据
  27. const getDatasHttp=async()=>{
  28. const data=await getPersonDatas()
  29. return {data}
  30. }
  31. const Person = () => {
  32. const actionRef = useRef<ActionType>();
  33. return (
  34. <div>
  35. <PageHeaderWrapper>
  36. <ProTable
  37. columns={columns}
  38. actionRef={actionRef}
  39. request={async (params = {}) => getDatasHttp()}
  40. editable={{
  41. type: 'multiple',
  42. }}
  43. rowKey="id"
  44. search={{
  45. labelWidth: 'auto',
  46. }}
  47. form={{
  48. // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
  49. syncToUrl: (values, type) => {
  50. if (type === 'get') {
  51. return {
  52. ...values,
  53. created_at: [values.startTime, values.endTime],
  54. };
  55. }
  56. return values;
  57. },
  58. }}
  59. pagination={{
  60. pageSize: 5,
  61. }}
  62. dateFormatter="string"
  63. headerTitle="高级表格"
  64. toolBarRender={() => [
  65. <Button key="button" icon={<PlusOutlined />} type="primary">
  66. 新建
  67. </Button>,
  68. ]}
  69. />
  70. </PageHeaderWrapper>
  71. </div>
  72. )
  73. }
  74. export default Person

2.通过redux实现交互

适用于多个页面公用一个数据

2.1配置redux

  1. //models/person.ts
  2. import {getPersonDatas}from "@/services/person"
  3. import { Effect,Reducer} from 'umi'
  4. interface IndexModelState {
  5. name: string;
  6. }
  7. interface IndexModelType {
  8. namespace :string,
  9. state:{
  10. persons:any[]
  11. },
  12. effects: {
  13. fetchPersons: Effect
  14. },
  15. reducers:{
  16. setPersons: Reducer<IndexModelState>;
  17. }
  18. }
  19. const personModel:IndexModelType={
  20. namespace:'person',
  21. state:{
  22. persons:[]
  23. },
  24. effects:{
  25. *fetchPersons(_,{call,put}){
  26. const data=yield call(getPersonDatas)
  27. yield put({
  28. type:'setPersons',
  29. payload:data
  30. })
  31. }
  32. },
  33. reducers:{
  34. setPersons(state:any,action:any){
  35. return {
  36. ...state,
  37. persons:action.payload
  38. }
  39. }
  40. }
  41. }
  42. export default personModel

2.2在组件中使用

  1. //src/pages/Person/index.tsx
  2. import React, { useRef, useEffect } from 'react';
  3. import { PageHeaderWrapper } from '@ant-design/pro-layout';
  4. import { PlusOutlined } from '@ant-design/icons';
  5. import { Button } from 'antd';
  6. import type { ActionType } from '@ant-design/pro-table';
  7. import ProTable from '@ant-design/pro-table';
  8. import { connect } from 'umi';
  9. const columns = [
  10. {
  11. title: '姓名',
  12. dataIndex: 'name',
  13. },
  14. {
  15. title: '年龄',
  16. dataIndex: 'age',
  17. hideInSearch: true,
  18. },
  19. {
  20. title: '性别',
  21. dataIndex: 'sex',
  22. hideInSearch: true,
  23. },
  24. ];
  25. //获取数据
  26. const Person = (props: any) => {
  27. const { dispatch }: any = props;
  28. useEffect(() => {
  29. //使用model,更新数据
  30. dispatch({
  31. //调用命名空间的某个方法
  32. type: 'person/fetchPersons',
  33. //需要传递的参数,这里可以传递一些发送请求所需要的参数
  34. payload: null,
  35. });
  36. }, []);
  37. const actionRef = useRef<ActionType>();
  38. // const getDatasHttp = () => {
  39. // const data = props.person.persons;
  40. // return { data };
  41. // };
  42. return (
  43. <div>
  44. <PageHeaderWrapper>
  45. <ProTable
  46. columns={columns}
  47. actionRef={actionRef}
  48. // request={async (params = {}) => getDatasHttp()}
  49. dataSource={props.person.persons}
  50. editable={{
  51. type: 'multiple',
  52. }}
  53. rowKey="id"
  54. search={{
  55. labelWidth: 'auto',
  56. }}
  57. form={{
  58. // 由于配置了 transform,提交的参与与定义的不同这里需要转化一下
  59. syncToUrl: (values, type) => {
  60. if (type === 'get') {
  61. return {
  62. ...values,
  63. created_at: [values.startTime, values.endTime],
  64. };
  65. }
  66. return values;
  67. },
  68. }}
  69. pagination={{
  70. pageSize: 5,
  71. }}
  72. dateFormatter="string"
  73. headerTitle="名单管理"
  74. toolBarRender={() => [
  75. <Button key="button" icon={<PlusOutlined />} type="primary">
  76. 新建
  77. </Button>,
  78. ]}
  79. />
  80. </PageHeaderWrapper>
  81. </div>
  82. );
  83. };
  84. //连接ui组件和容器组件
  85. export default connect(
  86. //这里得person与命名空间的值保持一致
  87. ({ person }: any) => ({ person }),
  88. )(Person);