博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

关于构建umi+dva+ant react项目附源码

Posted on 2022-04-29 18:02  yqphare  阅读(110)  评论(0编辑  收藏  举报

刚刚入门react,通过视频学习,做一个简单的react表格功能实现。功能满足对表格数据进行增删改,数据来源于后端接口。交互也与后端接口进行!

话不多说,直接看效果!

 

 

 

 接口设置了30%的概率报错,出现错误多刷新几次。

这是后端接口地址 https://public-api-v1.aspirantzhang.com/

 浏览器可以直接看到接口数据

 

 

 

项目的搭建是参照于umi官网的快速上手进行搭建的,想要试试的小伙伴可以先将项目搭建起来!https://umijs.org/zh-CN/docs/getting-started

 

 我们的项目主要集中在page下的users文件夹中的内容!

在page下新建uses文件夹

新建这几个文件

 

我们在components文件夹下放的文件的组件,UserModal,为弹出框组件

import React,{useEffect,FC} from "react";
import {Modal, Button ,Form,Input} from 'antd';
import {SingleUserType,FormValues} from '../data'


interface UserModalProps{
    visible:boolean;
    record:SingleUserType|undefined
    closeHandeler:()=>void
    onFinish:(values:FormValues)=>void
}
const UserModal :FC<UserModalProps> = (props)=>{
    const[form]=Form.useForm();
    const {visible,record,closeHandeler,onFinish} = props
    // useEffect(参数1,参数2)  当参数2发生改变时,执行参数1     参数1为函数,参数2为数组
    useEffect(()=>{
       
        if(record==undefined){
            form.resetFields();
        }
        else{
            form.setFieldsValue(record);
        }
    },[visible])

    const onOk=()=>{
        form.submit()
    }
        
      const onFinishFailed = () => {
        console.log('Submit failed!');
      };

    return(
        <div>
             <Modal title="基本信息"
              visible={visible}
               onOk={onOk}
               onCancel={closeHandeler}
               forceRender>
                   
          <Form
            name="basic"
            form={form} 
            onFinish={onFinish}
            onFinishFailed={onFinishFailed}
            >
            <Form.Item
                label="姓名"
                name="name"
                rules={[
                {
                    required: true,
                    message: 'Please input your name!',
                },
                ]}
            >
                <Input />
            </Form.Item>

            <Form.Item label="邮箱" name="email">
                <Input />
            </Form.Item>
            <Form.Item label="创建时间" name="create_time">
                <Input />
            </Form.Item>
            <Form.Item label="状态" name="status">
                <Input />
            </Form.Item>

          

            
    </Form>
        </Modal>
        </div>
    )
}
export default UserModal

 

在users文件夹下index为主页面,data.a为数据类型,model为模块文件,service为交互后端文件

 index.tsx

import React,{ FC, useState} from 'react';
import { Table,  Space,Modal, Button,Popconfirm,Tag } from 'antd';
import ProTable, { TableDropdown ,ProColumns, ActionType} from '@ant-design/pro-table';
import { connect,Dispatch, Loading,UserState } from 'umi';
import UserModal from './compoents/UserModal';
import {getRemoteList} from './service'

import {SingleUserType,FormValues} from './data.d'

interface UserPageProps{
  users:UserState,
  dispatch:Dispatch,
  userListLoading:boolean,
}

const UserListPage:FC<UserPageProps> =({users,dispatch,userListLoading})=>{
 
  const [modalVisible,setModalVisible]=useState(false)
  const [record,setRecord]=useState<SingleUserType|undefined>(undefined)
const columns = [
  {
    title: 'ID',
    dataIndex: 'id',
    key: 'id',
  },
  {
    title: '姓名',
    dataIndex: 'name',
    key: 'name',
    render:( text :string) => <a>{text}</a>,
  },
  {
    title: '邮箱',
    dataIndex: 'email',
    key: 'email',
    render: ( text :string) => <a>{text}</a>,
  },
  {
    title: '创建时间',
    dataIndex: 'create_time',
    key: 'create_time',
  },
  {
    title: '更新时间',
    dataIndex: 'update_time',
    key: 'update_time',
  },
  {
    title: '状态',
    dataIndex: 'status',
    key: 'status',
    render:tag=>{
      let color='#87d068'
      if(tag!==1){
       color = tag == 2 ? '#108ee9' : 'green'
      } 
      else{
        color='#f50'
      }
      return <Tag color={color} key={tag}>状态:{tag}</Tag>     

    }
  },
 
  {
    title: '操作',
    key: 'action',
    render: (text:string,record:SingleUserType) => (
      <Space size="middle">
       <a onClick={()=>{
         editHandler(record)
       }}>编辑</a>
       
       <Popconfirm
    title="确定要删除这条信息吗?"
    onConfirm={()=>{
      confirm(record)
    }}
    okText="Yes"
    cancelText="No"
  >
    <a href="#">删除</a>
  </Popconfirm>
      </Space>
    ),
  },
];

const editHandler=(record:SingleUserType)=>{   
      console.log(record)
      setModalVisible(true);
    setRecord(record);  
}
const closeHandeler=()=>{
   setModalVisible(false)
}
// 编辑确认
const onFinish = (values:FormValues) => {
  let id =0
  if(record){
    id=record.id;
  }
  if(id){
    console.log('edit')
    dispatch({
    type:'users/edit',
    payload:{
      id,
      values
    }
  })
}
else{
  console.log('add')
  dispatch({
    type:'users/add',
    payload:{
      values
    }
  })
}
 
  setModalVisible(false)
};
// 删除确定
const confirm=(record:SingleUserType)=>{
  const id=record.id
dispatch({
  type:'users/delete',
  payload:{
    id
  }
})

}
const addHandler=()=>{
  setModalVisible(true)
  setRecord(undefined)
}
const requestHandler= async ({pageSize,current})=>{
  console.log(pageSize,current)
  const users=await getRemoteList();
  return {
    data:users.data,
    success:true,
    total:users.meta.total,
  }

}

  return(
  <div className='list-table'>
    <Button type="primary" onClick={addHandler}>添加</Button>
    <ProTable 
    columns={columns} 
    dataSource={users.data} 
    rowKey='id' 
    loading={userListLoading} 
    request={requestHandler}
    search={false}
    />
   <UserModal visible={modalVisible} closeHandeler={closeHandeler} record={record} onFinish={onFinish}></UserModal>
  </div>
  )
};
const mapStateToProps = ({users,loading}:{users:UserState,loading:Loading})=>{
  console.log(loading)
  return{
    users,
    userListLoading:loading.models.users,
  }
}

export default connect(mapStateToProps)(UserListPage)

data.d.ts

export interface SingleUserType{
      "id": number,
      "name": string,
      "email": string ,
      "create_time": string ,
      "update_time": string,
      "status": number
}
export interface FormValues{
      [name:string]:any;
  }

model.ts

import {Reducer,Effect,Subscription} from 'umi'
import users from '.';
import {getRemoteList,editRecord,deleteRecord,addRecord} from './service'
import {SingleUserType} from './data.d'


export interface UserState{
    data:SingleUserType[],
    meta:{
        total:number;
        per_page:number;
        page:number;
    }
}

interface UserModelType{
    namespace:'users';
    state:UserState;
    reducers:{
        getList:Reducer<UserState>
    };
    effects:{
        getRemote:Effect
        edit:Effect
        delete:Effect
        add:Effect
    };
    subscriptions:{
        setup:Subscription;
    };

}
const UserModel: UserModelType = {
// 命名空间,也叫标识名
    namespace:'users',
    // 仓库数据初始值
    state:{
        data:[],
    meta:{
        total:0,
        per_page:5,
        page:1,
    }
    },
    // 同步
    //action相当于是{type,payload}  type:函数名  payload:数据
    reducers:{
        getList(state,{payload}){
            console.log("reducer here")
            return payload;
        }
       
    },
    
    // 异步 返回的是一个viod 只能通过reduces返回数据
    effects:{
        // 异步函数前要加*
        *getRemote(action,{put,call}){
            const data = yield call (getRemoteList)
              yield put({
                  type:'getList',
                  payload: data  
              })
        },
        *edit({payload:{id,values}},{put,call}){
            const data = yield call (editRecord,{id,values})
            yield put({
                type:'getRemote'
            })
        },
        *delete({payload:{id}},{put,call}){
            const data = yield call (deleteRecord,{id})
            yield put({
                type:'getRemote'
            })
        },
        *add({payload:{values}},{put,call}){
            const data = yield call (addRecord,{values})
            yield put({
                type:'getRemote'
            })
        },
      
    },
    // 订阅
    subscriptions:{
        setup({dispatch,history}){
           return  history.listen((location,action)=>{
                if(location.pathname=='/users'){
                    console.log("subscription here")
                    dispatch({
                        type:'getRemote',
                    });
                }
            });
        }
    }

};

// 导出model
export default UserModel;

service.ts

import { response } from "@umijs/deps/compiled/express";
import { request } from "umi"
import { message } from 'antd';
import { FormValues } from "./data";
export const getRemoteList =async () => {
    return request('/api/users',{
        method:'get',
        
    }).then(function(response){
        console.log("update ok")
        return response
        
    })
    .catch(function(error){
        console.log(error);
    })  
}
export const editRecord =async ({id,values}:{id:number,values:FormValues}) => {
    return request(`/api/users/${id}`,{
        method:'put',
        data:values
        
    }).then(function(response){
        message.success('修改成功!');
        
    })
    .catch(function(error){
        message.error('修改失败!');
    })  
}
export const deleteRecord =async ({id}:{id:number}) => {
    return request(`/api/users/${id}`,{
        method:'delete',
               
    }).then(function(response){
        message.success('删除成功!');
        
    })
    .catch(function(error){
        message.error('删除失败!');
    })  
}
export const addRecord =async ({values}:{values:FormValues}) => {
    return request(`/api/users/`,{
        method:'post',
        data:values
        
    }).then(function(response){
        message.success('添加成功!');
        
    })
    .catch(function(error){
        message.error('添加失败!');
    })  
}

其中路由配置了代理,可以参考我上一篇发布的文章https://www.cnblogs.com/yqPhare/p/16199595.html