关于antd Table

1、自定义Table的hook——useTable

         🍒关于实现table表格的需求中,会需要请求数据,分页,刷新,条件搜索等等行为逻辑。为避免代码的繁琐冗余,所以将其封装为一整个hook

a.关于定义useTable

import React, { useEffect, useReducer, useState } from 'react';
import { isUndefined } from "lodash-es";
import useDebounce from "@/hooks/useDebounce";

//默认初始条件
const initData = {
  data: [],
  count: 0,
  totalPage: 0,
  conditions: {
    pageSize: 10,
    pageNum: 1
  }
};
const tableHandler = (state, action) => {
  const { type, payload = {} } = action;
  if (type === 'INIT_DATA') {
    return Object.assign({}, state, {
      ...payload,
    });
  } else if (type === 'MODIFY_PAGES') {
    const { conditions } = state;
    const { pageSize = 10, pageNum = 1 } = payload;
    return Object.assign({}, state, {
      conditions: Object.assign({}, conditions, {
        ...payload
      }),
      pageSize,
      pageNum
    });
  } else if (type === 'MODIFY_CONDITION') {
    return {
      ...state,
      conditions: {
        ...state.conditions,
        ...payload
      }
    };
  } else if (type === 'CONCAT_DATA') {
    const { data, conditions } = state;
    const { pageSize, pageNum, ...rest } = payload;
    return Object.assign({}, state, {
      ...Object.assign({}, rest, {
        data: data.concat(payload.data),
      }, pageSize, pageNum
      )
    });
  } else if (type === 'RESET_CONDITIONS') {
      return {
        ...state,
        conditions: isUndefined(payload) ? initData.conditions : payload
      }
    }
  return state;
};
const useTable = (
    type, //自定义命名
    fetchTableData, //api
    initConditions = {}, //传入条件
    isFetch = true, //可手动控制是否请求的开关
    isLoadable = false
) => {
  const [isLoading, setIsLoading] = useState(false);
  const [tableData, dispatchTableData] = useReducer(tableHandler, Object.assign({}, 
  initData, {
    conditions: Object.assign({}, initData.conditions, initConditions),
  }), data => {
    return data;
  });
  const { cacheConditions } = useDebounce(tableData.conditions, 300, 
                              'cacheConditions');
  useEffect(() => {
    if (fetchTableData && isFetch) {
      fetchData(cacheConditions);
    }
  }, [cacheConditions, isFetch]);

//请求api
  const fetchData = async conditions => {
    setIsLoading(true);
    const { pageSize, pageNum, ...rest } = conditions;
    fetchTableData({
      pageNum,
      pageSize,
      ...rest
    }).then(res => {
      if (res && res.code === 0 || (res && res.data)) {
        const { pageNum } = res;
        if (pageNum !== 1 && isLoadable) {
          dispatchTableData({
            type: 'CONCAT_DATA',
            payload: res
          });
        } else {
          dispatchTableData({
            type: 'INIT_DATA',
            payload: res
          });
        }
      }
      setIsLoading(false);
    });
  };
//翻页动作
  const modifyPages = (pageNum, pageSize) => {
    dispatchTableData({
      type: 'MODIFY_PAGES',
      payload: {
        pageNum,
        pageSize
      }
    });
  };
//搜索动作
  const modifyConditions = (conditions) => {
    dispatchTableData({
      type: 'MODIFY_CONDITION',
      payload: conditions
    });
  };
//强制刷新
  const forceRefresh = (pageNum, pageSize = tableData.conditions.pageSize) => {
    fetchTableData({
      ...tableData.conditions,
      pageNum: !isUndefined(pageNum) ? pageNum : tableData.pageNum,
      pageSize: pageSize,
    }).then(res => {
      dispatchTableData({
        type: 'INIT_DATA',
        payload: res
      });
    });
  };
  
//滚动加载
  const onScroll = (e) => {
    const {target} = e
    const {pageNum, totalPage, pageSize} = tableData
    if (target.scrollTop + target.offsetHeight >= target.scrollHeight) {
      if (currentPage + 1 > totalPage) {
        return
      }
      modifyPages(pageSize, pageNum + 1)
    }
  }

//条件重置
  const resetConditions = (payload) => {
    dispatchTableData({
      type: 'RESET_CONDITIONS',
      payload
    })
  }

  return type ? {
    [`${type}TableData`]: tableData,
    [`dispatch${type.split('').map((i, index) => index === 0 ? i.toUpperCase() : i).join('')}TableData`]: dispatchTableData,
    modifyPages,
    forceRefresh,
    modifyConditions,
    isLoading,
    conditions: cacheConditions,
    customFetchData: fetchData,
    onScroll,
    resetConditions
  } : {
    tableData,
    dispatchTableData,
    modifyPages,
    forceRefresh,
    modifyConditions,
    isLoading,
    conditions: cacheConditions,
    customFetchData: fetchData,
    onScroll,
    resetConditions
  };
};

export default useTable; 

 b.关于使用useTable

//useTable初始条件:
//     1.可自定义tableData的名字(必填,或为undefined)
//     2.获取table数据的api(必填)
//     3.api参数
const {
    xxxTableData,
    modifyPages,
    forceRefresh,
    modifyConditions,
    isLoading,
    onScroll,//如需滚动加载,将其放到上层dom
  } = useTable('xxx', getListApi, {pageSize: 10000});

//解构xxxTableData
const { dataSource, pagination } = useMemo(() => {
    const {
      data,
      conditions: {
        pageSize,
        pageNum
      },
      count
    } = xxxTableData || {};
    return {
      dataSource: data,
      pagination: {
        pageSize,
        current: pageNum,
        total: count,
      },
    };
  }, [xxxTableData])

const getPage = (pageNum, pageSize) => modifyPages(pageSize, pageNum)

<Table 
  loading={isLoading}
  pagination={{
       ...pagination,
       onChange: getPage,
       onShowSizeChange: getPage,
       showSizeChanger: true,
       showTotal: (total) => 共{total}条,
       showQuickJumper: true,
  }} 
  dataSource={dataSource} 
  columns={columns}
/>

⏰以上可以实现大部分的table操作行为。但在项目中还是遇到些比较刁钻的逻辑,以至于不断将useTable进行改造,我就不补充了。。。希望大家遇不到

2、关于Table单元格改造

  🍒在实际需求中会要求单元格的底色可动态变化

a.实现当前列底色动态变化

{
    title: '等级',
    dataIndex: 'level',
    key: 'level',
    align: 'left',
    isResize: true,
    width: 200,
    render: (text = {}, record) => {
        const { level } = record
        return {
            props: {
              style: { 
                background: colorEnum[level.toLowerCase()]
              }
            },
            children: <div>{text}</div>
          };
        }
}

b.实现当前整行底色动态变化

     🍒利用Table的rowClassName属性自定义类名

const onClickRowStyle = (record, rowIndex) => {
    return 'xxx' + record.level 
  }
return <Table
  rowClassName={(record, rowIndex) => onClickRowStyle(record, rowIndex)}
/>

<Table/>

css部分

.ant-table .ant-table-content .ant-table-tbody {
     >tr.xxx-ok {
       background: #fff;
     }
     >tr.xxx-minor {
       background: #87CEEB;
     }
     >tr.xxx-moderate {
       background: #FFFF00;
     }
     >tr.xxx-major {
       background: #FFD700;
     }
     >tr.xxx-critical {
      background: #EE2C2C;
     }
  }

c.项目中遇到要求整行底色不为固定,为可配置情况

   1.首先还是自定义类名

const onClickRowStyle = (record, rowIndex) => {
    return 'xxx' + record.level 
  }
return <Table
  rowClassName={(record, rowIndex) => onClickRowStyle(record, rowIndex)}
/>

<Table/>

    2.再将样式在当前table注入 

//此colorMap为api获取,在这里先写死了
const colorMap = {
   'ok': '#fff',
   'critical':'#fff',
   'major':'#fff',
   'minor':'#fff',
}

return <>
<Table
  rowClassName={(record, rowIndex) => onClickRowStyle(record, rowIndex)}
/>
<style jsx>
      {`
        :global(.xxx-ok){
          background-color:${colorMap['ok']};
        }
        :global(.xxx-critical){
          background-color:${colorMap['critical']};
        }
        :global(.xxx-major){
          background-color:${colorMap['major']};
        }
        :global(.xxx-minor){
          background-color:${colorMap['minor']};
        }
      `}
</style>
</>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值