react之a(chǎn)ntd table二次封裝

阿里出品的Ant Design UI組件用起來(lái)可以說(shuō)是很順手的,但是用多了會(huì)發(fā)現(xiàn)有時(shí)候還能更高效一點(diǎn),那么我就萌生了對(duì)個(gè)別組件驚醒二次封裝的念頭启盛,接下來(lái)我就介紹下我二次封裝的表格組件霜第,事先說(shuō)明:以下組件是基于antdV3版本的葛家,V4版本使用分頁(yè)會(huì)存在問(wèn)題(已解決待下次更新)
詳細(xì)說(shuō)明見git倉(cāng)庫(kù) --->二次封裝代碼傳送門
如果登不上可以去gitee=》二次封裝代碼傳送門
有積分得也可以直接在csdn下載(謝謝各位老板)=》二次封裝代碼壓縮包
下面我將分模塊的介紹下我的封裝思路及各個(gè)部門的功能

參數(shù)說(shuō)明

TableComponent.propTypes = { //.propTypes是react規(guī)定的名稱,不可以修改
  tableData: PropTypes.shape({
    url: PropTypes.string.isRequired, // 路徑類型
    rowSelection: PropTypes.bool, // 復(fù)選標(biāo)識(shí)
    lineIndex: PropTypes.bool, // 序號(hào)標(biāo)識(shí)
    columns: PropTypes.array.isRequired, // 列參數(shù)
    dataToOut: PropTypes.bool, // 數(shù)據(jù)外傳標(biāo)識(shí)
    addParams: PropTypes.object, // 新增參數(shù)
    size: PropTypes.oneOf(['default', 'middle', 'small']), // 表格尺寸
    handleOverflow: PropTypes.bool, // 全局溢出處理,不需要再單獨(dú)每個(gè)列設(shè)置(設(shè)置后忽略單獨(dú)設(shè)置)
    falseData: PropTypes.array, // 假數(shù)據(jù)
    method: PropTypes.oneOf(['get', 'post']), // 請(qǐng)求方式
    changePageParam:PropTypes.objectOf(function(propValue, key, componentName, location, propFullName) {
      let allowKeys = [ 'pageSize', 'page', 'totalCount', 'list' ]
      if (allowKeys.indexOf(key) < 0 ) { 
        return new Error(
          'Invalid prop `' + componentName + '` supplied to' +
          ' `' + propFullName + '`. Validation failed.'
        );
      }
    }), // 替代頁(yè)面參數(shù)
    scroll: PropTypes.object, // 滾動(dòng)配置
  }),

  // 列新參數(shù)說(shuō)明(由于不知道怎么設(shè)置tableData.columns的參數(shù)類型泌类,
  // 所以暫放在這癞谒,但組件沒(méi)有這個(gè)參數(shù))
  Columns: PropTypes.shape({
    overflow: PropTypes.bool, // 列移除處理(移除顯示省略號(hào)...)
  })
};

基礎(chǔ)顯示

基礎(chǔ)列表顯示功能只需要一個(gè)地址參數(shù)url和列參數(shù)columns就可以實(shí)現(xiàn)列表的顯示,當(dāng)然刃榨,前提是你請(qǐng)求參數(shù)為

pageData: { 
  [pageSize]: 10, // 變量屬性名弹砚,ES6標(biāo)準(zhǔn),實(shí)現(xiàn)自定義請(qǐng)求體,兼容不同的后端請(qǐng)求體實(shí)體類
  [page]: 1,
},

并且沒(méi)有其他的篩選參數(shù)枢希,這樣通過(guò)getData方法就是獲取列表參數(shù)桌吃。getData()如下:

 /**
   * 獲取表格數(shù)據(jù)
   * @param p 參數(shù)
   */
  getData(p) {
    let _this = this.props.tableData;
    // 請(qǐng)求方式再設(shè)置(tabs切換時(shí)不會(huì)刷新標(biāo)簽頁(yè)內(nèi)容,所以需要重置請(qǐng)求體
    // 否則兩個(gè)標(biāo)簽頁(yè)請(qǐng)求體不同時(shí)點(diǎn)擊切換標(biāo)簽頁(yè)并跳轉(zhuǎn)頁(yè)會(huì)報(bào)405錯(cuò)誤)
    setMethod(_this);
    // 參數(shù)再設(shè)置(同個(gè)頁(yè)面兩個(gè)table相互切換時(shí)苞轿,tableData會(huì)更新轉(zhuǎn)換茅诱,
    // 但是自定義參數(shù)不會(huì)轉(zhuǎn)換为流,需要手動(dòng)判斷)
    if (_this.changePageParam && Object.keys(_this.changePageParam).length > 0) {
      this.newParam(_this.changePageParam);
    }
    if (_this.url) {
      // 篩選換頁(yè)加載中樣式
      this.setState({
        loading: true
      });
      // 獲取表格顯示數(shù)據(jù)
      api[_method](_this.url, p).then(res => {
        res = this.traverse(res); // 污染原始數(shù)據(jù)
        if (res[list].length > 0) {
          // 表格數(shù)據(jù)添加key值
          let index;
          for (const key in res[list]) {
            if (res[list].hasOwnProperty(key)) {
              index = p[pageSize]*(p[page] - 1) + Number(key)
              res[list][key]['onlyKey'] = index;
            }
          }
          this.setState({
            pagination: {
              ...this.state.pagination,
              total: res[totalCount],
            },
            loading: false, // 關(guān)閉加載中
          })
          if (_this.dataToOut) {
            this.props.getTableDatas(res); // 表格數(shù)據(jù)外送處理
          } else {
            this.setState({
              data: res[list],
            })
          }      
        } else {
          // message.warn('獲取列表信息為空!')
          if (_this.dataToOut) this.props.getTableDatas(res); // 表格數(shù)據(jù)外送處理
          this.setState({
            loading: false,
            data: [],
            pagination: {
              ...this.state.pagination,
              total: res[totalCount],
            },
          })
        }
      }).catch(err => { 
        if (_this.dataToOut) this.props.getTableDatas(); // 表格數(shù)據(jù)外送處理
        this.setState({
          loading: false,
          data: [],
          pagination: {
            ...this.state.pagination,
            total: 0,
          },
        })
        // message.error('獲取信息失斎貌尽敬察!')
        log('err: '+ err);
      })
    } else {
      // message.error('接口路徑不得為空!')
      log('接口路徑不得為空!')
      this.setState({
        loading: false
      })
    }
  }

切記:在外送數(shù)據(jù)處理后一定要調(diào)用inputData ()傳入數(shù)據(jù),否則表格將不顯示尔当。

自定義請(qǐng)求體返回體

在getData()方法里的備注里已經(jīng)有簡(jiǎn)單的提到了莲祸,接下來(lái)詳細(xì)說(shuō)明下。主要是通過(guò)參數(shù)changePageParam實(shí)現(xiàn)椭迎,使用方法詳見源代碼md文件锐帜,實(shí)現(xiàn)方法看下es6變量屬性名和組件里的traverse()方法

changePageParam: {page:'pageNo',totalCount:'total',pagesize:'xxx',list: 'list'},

組件里有四個(gè)對(duì)外的參數(shù),也就是列表必須的四個(gè)參數(shù):頁(yè)數(shù)page畜号,頁(yè)條數(shù)pagesize缴阎,返回列表屬性名:list返回總條數(shù)屬性名:totalCount。有了這四個(gè)參數(shù)基本的顯示肯定是沒(méi)問(wèn)題的简软,再根據(jù)你們定義的參數(shù)名對(duì)應(yīng)進(jìn)行修改就可自定義請(qǐng)求體返回體蛮拔。這樣是達(dá)到了自定義請(qǐng)求體返回體的效果,但同時(shí)也埋了個(gè)雷痹升,就是頁(yè)面使用多個(gè)表格組件時(shí)參數(shù)不一樣的話分頁(yè)/請(qǐng)求會(huì)出問(wèn)題建炫,還沒(méi)想到好的解決辦法。疼蛾。肛跌。

篩選功能

通過(guò)調(diào)用inputParam()方法實(shí)現(xiàn),代碼如下:

 /**
   * 傳入新參數(shù)進(jìn)行篩選
   * @param p 新參數(shù)(為空表示重置)
   */
  inputParam(p = {}) {
    let param = {};
    if (Object.keys(p).length === 0) {
      param = {
        ...this.state.addParam, // 全局字段
        [pageSize]: this.state.pageData[pageSize],
        [page]: 1, // 頁(yè)碼
      }
      // 將新增參數(shù)寫入state,避免分頁(yè)報(bào)錯(cuò)
      this.setState({
        pageData: {
          ...param
        },
        pagination: {
          ...this.state.pagination,
          current: 1
        },
        screenParam: {},
      })
    } else {
      param = {
        ...this.state.pageData,
        [page]: 1, // 頁(yè)碼
        ...this.state.addParam, // 全局字段
        ...p,
      }
      // 將新增參數(shù)寫入state,避免分頁(yè)報(bào)錯(cuò)
      this.setState({
        pageData: {
          ...this.state.pageData,
            [page]: 1, // 頁(yè)碼
        },
        pagination: {
          ...this.state.pagination,
          current: 1
        },
        screenParam: p,
      })
    }
    this.getData(param);
  }

使用詳見源代碼md文件方法說(shuō)明察郁。

多選實(shí)現(xiàn)和??選實(shí)現(xiàn):

多選實(shí)現(xiàn)就是沿用antd的方法設(shè)置rowSelection:true
禁選的設(shè)置通過(guò)調(diào)用setUnselect(param, key, type)方法衍慎,代碼如下:

 /**
   * 多選后不可選設(shè)置
   * @param key 判斷值
   */
  setCheckboxProps (key){
    // 判斷多選啟用
    if (this.props.tableData.rowSelection) {
      this.setState({
        checkboxPropsKey: key
      })
      this.getCheckboxProps(null, key)
    }
  }
  /**
   * 表格不可選條目設(shè)置
   * @param param 字段
   * @param key 不可選判斷
   * @param type 判斷類型(true:record[unselectPar] === unselect是不可選,false:record[unselectPar] !== unselect是不可選)
   */
  setUnselect(param, key, type=undefined){
    unselectPar = param;
    this.setState({unselect: key})
    if (type === false) {
      this.setState({unselectType: false})
    } else {
      this.setState({unselectType: true})
    }
    this.getCheckboxProps(null, undefined, key)
  }
// 多選回調(diào)函數(shù)
  onSelectChange = (selectedRowKeys, selectedRows) => {
    // console.log(selectedRowKeys);
    if (selectedRows.length === 0) {
      this.setState({checkboxPropsKey: undefined})
    }
    this.setState({ selectedRowKeys });
    this.props.getSelectData(selectedRows);
  };
  /**
   * 多選設(shè)置
   * @param record 列表
   * @param key 選擇后不可選key值
   * @param unselect 列表不可選設(shè)置
   */
  getCheckboxProps = (record, key=undefined, unselect=undefined) => {
    if (record !== null && key !== undefined) {
      return({
        disabled: record.onlyKey !== key, // Column configuration not to be checked
      })
    }
    if (record !== null && key === undefined && unselect !== undefined) {
      if (this.state.unselectType) {
        return({
          disabled: record[unselectPar] === unselect, // 相等時(shí)不可選
        })
      } else {
        return({
          disabled: record[unselectPar] !== unselect, // 不等時(shí)不可選
        })
      }
    }
  };

使用詳見源代碼md文件方法說(shuō)明

表格刷新

又是外部需要手動(dòng)刷新表格內(nèi)容皮钠,就可以調(diào)用refresh()方法稳捆,代碼如下:

  /**
   * 表格刷新
   */
  refresh() {
    const { addParam, screenParam, pageData } = this.state
    const param = {
      ...addParam, 
      ...screenParam, 
      ...pageData
    }
    this.getData(param)
    this.setState({ selectedRowKeys: [] }) // 多選清空
  }

使用詳見源代碼md方法說(shuō)明

清除多選

有時(shí)不想刷新表格只想清楚多選,可以調(diào)用cleanSelectedRow()方法鳞芙,代碼如下:

  // 清除多選
  cleanSelectedRow(){
    this.setState({selectedRowKeys: []}) // 多選清空
  }

使用詳見源代碼md文件方法說(shuō)明

單元格超長(zhǎng)溢出處理

單獨(dú)列的溢出處理可以使用columns參數(shù)里的overflow搭配width設(shè)置寬度眷柔,超過(guò)顯示省略號(hào)期虾。
全部設(shè)置的話使用handleOverflow參數(shù)原朝,這樣搭配列參數(shù)的width設(shè)置寬度,超過(guò)顯示省略號(hào)镶苞,就不用挨個(gè)列的設(shè)置overflow了喳坠。當(dāng)然也可以使用antd自帶的ellipsis屬性,待筆者有空完善下茂蚓。壕鹉。剃幌。
注意: 如果你的列參數(shù)設(shè)置了 render = (text) =>{} 方法這樣溢出處理就失效了,只能超過(guò)換行晾浴。具體原因詳見源碼componentWillMount ... // 生命周期添加內(nèi)容溢出處理负乡,當(dāng)然也是能解決的,但是筆者懶得去動(dòng)了脊凰,用的地方不多抖棘,等需求多了我在兼容處理下。

其他功能

還有比如排序狸涌,假數(shù)據(jù)顯示切省,請(qǐng)求體修改這幾個(gè)功能也都是支持的,具體使用詳見源代碼md文件方法說(shuō)明

已知bug

同頁(yè)面存在多個(gè)表格組件時(shí)會(huì)存在串參數(shù)的問(wèn)題帕胆,導(dǎo)致請(qǐng)求出錯(cuò)朝捆、分頁(yè)出錯(cuò)、排序顯示NaN問(wèn)題懒豹。

不足之處

  • 無(wú)法實(shí)現(xiàn)內(nèi)置行編輯
    由于V3版本表達(dá)的在封裝芙盘,如果加上行編輯那么之前版本的refs都不能用了,代價(jià)太大脸秽,使用率也低所以放棄何陆。
  • 分頁(yè)處理
    分頁(yè)處理的代碼其實(shí)可以優(yōu)化下的,不需要那么復(fù)雜豹储,可以使用組件自帶onChange方法更簡(jiǎn)潔的實(shí)現(xiàn)贷盲。
  • 還有很多...
    最后希望各位讀者能夠賞臉試用下我的組件,或者給我提出其他修改優(yōu)化的寶貴意見剥扣,筆者再這先謝謝大家了巩剖。 有問(wèn)題或者發(fā)現(xiàn)bug或者有新需求都可以在git上留言或者直接這下面留言,筆者一定第一時(shí)間解決钠怯,謝謝各位大哥賞臉試用佳魔,謝謝謝謝!;薮丁>舷省!断国!

二次封裝源碼

import React, { Component } from 'react';
import { Table, message, Tooltip } from 'antd';
import PropTypes from 'prop-types';
import './index.less'
import api from './network'

let { log, error } = console;
let page = 'page'; // 頁(yè)碼變量
let pageSize = 'pageSize'; // 頁(yè)條數(shù)
let totalCount = 'totalCount'; // 總條數(shù)
let unselectPar = undefined; // 不可選判斷字段
let list = 'list'; // 列表
let _method = 'post'; // 請(qǐng)求方式

// 公共方法
// 設(shè)置請(qǐng)求體
function setMethod(params) {
  let _this = params;
  // 請(qǐng)求方式
  try {
    if (_this.method === 'post' || _this.method === 'get') {
      _method = _this.method;
    } else if (_this.method === undefined || _this.method === null) {
      _method = 'post';
    } else{
      throw new Error('Request method `'+_this.method + '` is not allowed')
    }
  } catch (err) {
    error(err);
  }
}

class TableComponent extends Component {
  constructor(props) {
    super(props)
    // 全局變量重置默認(rèn)值
    page = 'page'; // 頁(yè)碼變量
    pageSize = 'pageSize'; // 頁(yè)條數(shù)
    totalCount = 'totalCount'; // 總條數(shù)
    unselectPar = undefined; // 不可選判斷字段
    list = 'list'; // 列表
    _method = 'post'; // 請(qǐng)求方式
    let _this = this.props.tableData;
    // 請(qǐng)求方式
    setMethod(_this);
    
    // 判斷是否使用新頁(yè)面參數(shù)
    if (_this.changePageParam && Object.keys(_this.changePageParam).length > 0) {
      this.newParam(_this.changePageParam);
    }
    this.state = {
      data: [],
      pageData: { 
        [pageSize]: 10,
        [page]: 1,
      }, 
      // 分頁(yè)參數(shù)
      pagination: {
        position: 'bottom',
        total: 0,
        showTotal: total => `共計(jì) ${total} 條`,
        pageSize: 10,
        pageSizeOptions: ['10', '20', '50', '100'],
        showSizeChanger: true,
        // 頁(yè)碼贤姆、條數(shù)變化回調(diào)
        onShowSizeChange: this.pageSizeChange,
        onChange: this.pageChange,
        current: 1
      },
      // 加載中
      loading: true,
      size: 'default',
      columns: [], // 列數(shù)據(jù)
      addParam: {}, // 全局參數(shù)字段存放
      screenParam: {}, // 篩選參數(shù)字段存放
      selectedRowKeys: [], // Check here to configure the default column
      checkboxPropsKey: undefined, // 多選比較值
      unselect: undefined, // 列表不可選
      unselectType: true, // 判斷類型,相等不可選還是不等時(shí)不可選
    }
    // console.log(this.state.pagination);
  }
  componentWillMount() {
    let _this = this.props.tableData;
    // 添加序號(hào)
    if (_this.lineIndex) {
      const index = {
        title: '序號(hào)',
        // width: 70, 
        align: 'center',
        render: (text, record, index) => `${index + 1 + (this.state.pageData[page] - 1) * this.state.pageData[pageSize]}`
      }
      _this.columns.unshift(index); // 數(shù)組頭部插入
    }
    // 添加內(nèi)容溢出處理
    if (_this.handleOverflow) { // 全局溢出處理
      for (const key in _this.columns) {
        if (_this.columns.hasOwnProperty(key)) {
          const element = _this.columns[key];
          if (element.width && !element.render) {
            _this.columns[key]['onCell'] = () => {
              return {
                style: {
                  maxWidth: element.width,
                  overflow: 'hidden',
                  whiteSpace: 'nowrap',
                  textOverflow:'ellipsis',
                  cursor:'pointer'
                }
              }
            }
            _this.columns[key]['render'] = (text) => <Tooltip placement="topLeft" title={text}>{text}</Tooltip>
          } else if (element.width && element.render){ // 存在render屬性時(shí)不生效
            // message.warn('第'+(Number(key)+1)+'列render屬性已經(jīng)存在稳衬!請(qǐng)移除后再設(shè)置溢出處理霞捡。')
          }
        }
      }
    } else {
      // 不做全局處理,單獨(dú)每一列的溢出處理
      for (const key in _this.columns) {
        if (_this.columns.hasOwnProperty(key)) {
          const element = _this.columns[key];
          if (element.width && !element.render && element.overflow) {
            _this.columns[key]['onCell'] = () => {
              return {
                style: {
                  maxWidth: element.width,
                  overflow: 'hidden',
                  whiteSpace: 'nowrap',
                  textOverflow:'ellipsis',
                  cursor:'pointer'
                }
              }
            }
            _this.columns[key]['render'] = (text) => <Tooltip placement="topLeft" title={text}>{text}</Tooltip>
          }
        }
      }
    }
    const param = {
      ...this.state.pageData,
      ..._this.addParams,
    }
    
    this.setState({
      pageData: {
        ...param
      },
      addParam: _this.addParams, // 儲(chǔ)存新參數(shù)
      columns: _this.columns,
      size: _this.size,
    })
    
// 尺寸設(shè)置
    if (_this.size) this.setState({ size: _this.size });
    // 假數(shù)據(jù)使用
    if (_this.falseData) { 
      this.setState({ data: _this.falseData, loading: false });
    } else { this.getData(param) }
  }
  /**
   * 自定義請(qǐng)求體薄疚、返回體
   * @param _newParam 新參數(shù)
   */
  newParam(_newParam){
    let arrKeys = Object.keys(_newParam);
    arrKeys.map( name =>{
      if (name === 'pageSize') { pageSize = _newParam.pageSize; return name; } 
      if (name === 'page') { page = _newParam.page; return name; }
      if (name === 'totalCount') { totalCount = _newParam.totalCount; return name; }
      if (name === 'list') { list = _newParam.list; return name; }
      return undefined;
    })
  }
  /** ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓----------向外開放方法--------↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
  /**
   * 接收外部數(shù)據(jù)
   * @param data 顯示數(shù)據(jù)
   */
  inputData = (data) => {
    this.setState({
      data
    })
  }
  /**
   * 傳入新參數(shù)進(jìn)行篩選
   * @param p 新參數(shù)(為空表示重置)
   */
  inputParam(p = {}) {
    let param = {};
    if (Object.keys(p).length === 0) {
      param = {
        ...this.state.addParam, // 全局字段
        [pageSize]: this.state.pageData[pageSize],
        [page]: 1, // 頁(yè)碼
      }
      // 將新增參數(shù)寫入state,避免分頁(yè)報(bào)錯(cuò)
      this.setState({
        pageData: {
          ...param
        },
        pagination: {
          ...this.state.pagination,
          current: 1
        },
        screenParam: {},
      })
    } else {
      param = {
        ...this.state.pageData,
        [page]: 1, // 頁(yè)碼
        ...this.state.addParam, // 全局字段
        ...p,
      }
      // 將新增參數(shù)寫入state,避免分頁(yè)報(bào)錯(cuò)
      this.setState({
        pageData: {
          ...this.state.pageData,
            [page]: 1, // 頁(yè)碼
        },
        pagination: {
          ...this.state.pagination,
          current: 1
        },
        screenParam: p,
      })
    }
    this.getData(param);
  }
  /**
   * 多選后不可選設(shè)置
   * @param key 判斷值
   */
  setCheckboxProps (key){
    // 判斷多選啟用
    if (this.props.tableData.rowSelection) {
      this.setState({
        checkboxPropsKey: key
      })
      this.getCheckboxProps(null, key)
    }
  }
  /**
   * 表格不可選條目設(shè)置
   * @param param 字段
   * @param key 不可選判斷
   * @param type 判斷類型(true:record[unselectPar] === unselect是不可選碧信,false:record[unselectPar] !== unselect是不可選)
   */
  setUnselect(param, key, type=undefined){
    unselectPar = param;
    this.setState({unselect: key})
    if (type === false) {
      this.setState({unselectType: false})
    } else {
      this.setState({unselectType: true})
    }
    this.getCheckboxProps(null, undefined, key)
  }

  /**
   * 表格刷新
   */
  refresh() {
    const { addParam, screenParam, pageData } = this.state
    const param = {
      ...addParam, 
      ...screenParam, 
      ...pageData
    }
    this.getData(param)
    this.setState({ selectedRowKeys: [] }) // 多選清空
  }
  // 清除多選
  cleanSelectedRow(){
    this.setState({selectedRowKeys: []}) // 多選清空
  }

  /** ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓----------組件內(nèi)部函數(shù)--------↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */
  /**
   * 遞歸操作赊琳,獲取隨機(jī)返回體內(nèi)的列表參數(shù)
   * 當(dāng)對(duì)象中存在 list 和 totalCount 是基本可以確定這就是所需要的列表參數(shù)
   * 再加以列表長(zhǎng)度判斷,雖然這樣基本能保證列表參數(shù)的唯一星砰碴,但是還有極概率存在出現(xiàn)問(wèn)題
   * 長(zhǎng)度判斷擔(dān)心不可靠躏筏,故暫未加上。
   */
  traverse(obj) {
    if (obj[list] && !isNaN(obj[totalCount])) {
      if (this.state.pageData[pageSize] !== obj[list].length) log('列表長(zhǎng)度不等于頁(yè)條數(shù)');
      return obj;
    } else {
      for (let a in obj) {
        if (typeof(obj[a]) === 'object') return this.traverse(obj[a]); //遞歸遍歷
      }
    }
  }
  /**
   * 獲取表格數(shù)據(jù)
   * @param p 參數(shù)
   */
  getData(p) {
    let _this = this.props.tableData;
    // 請(qǐng)求方式再設(shè)置(tabs切換時(shí)不會(huì)刷新標(biāo)簽頁(yè)內(nèi)容呈枉,所以需要重置請(qǐng)求體
    // 否則兩個(gè)標(biāo)簽頁(yè)請(qǐng)求體不同時(shí)點(diǎn)擊切換標(biāo)簽頁(yè)并跳轉(zhuǎn)頁(yè)會(huì)報(bào)405錯(cuò)誤)
    setMethod(_this);
    // 參數(shù)再設(shè)置(同個(gè)頁(yè)面兩個(gè)table相互切換時(shí)寸士,tableData會(huì)更新轉(zhuǎn)換,
    // 但是自定義參數(shù)不會(huì)轉(zhuǎn)換碴卧,需要手動(dòng)判斷)
    if (_this.changePageParam && Object.keys(_this.changePageParam).length > 0) {
      this.newParam(_this.changePageParam);
    }
    if (_this.url) {
      // 篩選換頁(yè)加載中樣式
      this.setState({
        loading: true
      });
      // 獲取表格顯示數(shù)據(jù)
      api[_method](_this.url, p).then(res => {
        res = this.traverse(res); // 污染原始數(shù)據(jù)
        if (res[list].length > 0) {
          // 表格數(shù)據(jù)添加key值
          let index;
          for (const key in res[list]) {
            if (res[list].hasOwnProperty(key)) {
              index = p[pageSize]*(p[page] - 1) + Number(key)
              res[list][key]['onlyKey'] = index;
            }
          }
          this.setState({
            pagination: {
              ...this.state.pagination,
              total: res[totalCount],
            },
            loading: false, // 關(guān)閉加載中
          })
          if (_this.dataToOut) {
            this.props.getTableDatas(res); // 表格數(shù)據(jù)外送處理
          } else {
            this.setState({
              data: res[list],
            })
          }      
        } else {
          // message.warn('獲取列表信息為空弱卡!')
          if (_this.dataToOut) this.props.getTableDatas(res); // 表格數(shù)據(jù)外送處理
          this.setState({
            loading: false,
            data: [],
            pagination: {
              ...this.state.pagination,
              total: res[totalCount],
            },
          })
        }
      }).catch(err => { 
        if (_this.dataToOut) this.props.getTableDatas(); // 表格數(shù)據(jù)外送處理
        this.setState({
          loading: false,
          data: [],
          pagination: {
            ...this.state.pagination,
            total: 0,
          },
        })
        // message.error('獲取信息失敗住册!')
        log('err: '+ err);
      })
    } else {
      // message.error('接口路徑不得為空!')
      log('接口路徑不得為空!')
      this.setState({
        loading: false
      })
    }
  }
  // 頁(yè)碼改變事件
  pageChange = (newPage) => {
    let pageData = {
      [pageSize]: this.state.pageData[pageSize], // 每頁(yè)的記錄數(shù)字
      ...this.state.addParam,
      ...this.state.screenParam
    }
    pageData[[page]] = newPage;
    this.setState({
      // selectedRowKeys: [], // 清空多選
      pageData: {
        [page]: newPage,
        [pageSize]: this.state.pageData[pageSize],
      },
      pagination: {
        current: newPage, // 當(dāng)前頁(yè)高亮
      }
    })
    this.getData(pageData);
  };

  // 頁(yè)顯示條數(shù)改變事件
  pageSizeChange = (e, newPageSize) => {
    this.setState({
      pageData: {
        [page]: 1,
        [pageSize]: newPageSize
      },
      pagination: {
        ...this.state.pagination,
        pageSize: newPageSize,
        current: 1
      }
    })
    const pageData = {
      [pageSize]: newPageSize, // 每頁(yè)的記錄數(shù)字
      [page]: 1, // 頁(yè)碼
      ...this.state.addParam,
      ...this.state.screenParam
    }
    this.getData(pageData);
  };
  // 多選回調(diào)函數(shù)
  onSelectChange = (selectedRowKeys, selectedRows) => {
    // console.log(selectedRowKeys);
    if (selectedRows.length === 0) {
      this.setState({checkboxPropsKey: undefined})
    }
    this.setState({ selectedRowKeys });
    this.props.getSelectData(selectedRows);
  };
  /**
   * 多選設(shè)置
   * @param record 列表
   * @param key 選擇后不可選key值
   * @param unselect 列表不可選設(shè)置
   */
  getCheckboxProps = (record, key=undefined, unselect=undefined) => {
    if (record !== null && key !== undefined) {
      return({
        disabled: record.onlyKey !== key, // Column configuration not to be checked
      })
    }
    if (record !== null && key === undefined && unselect !== undefined) {
      if (this.state.unselectType) {
        return({
          disabled: record[unselectPar] === unselect, // 相等時(shí)不可選
        })
      } else {
        return({
          disabled: record[unselectPar] !== unselect, // 不等時(shí)不可選
        })
      }
    }
  };

  render() {
    let _this = this.props.tableData;
    if (_this.changePageParam && Object.keys(_this.changePageParam).length > 0) {
      this.newParam(_this.changePageParam);
    }
    const tableList = {
      pagination: this.state.pagination,
      loading: this.state.loading,
    };
    const { selectedRowKeys } = this.state;
    const columns = this.state.columns;
    // 多選
    const Selection = {
      selectedRowKeys,
      onChange: this.onSelectChange,
      getCheckboxProps: (e) => this.getCheckboxProps(e, this.state.checkboxPropsKey, this.state.unselect),
    };
    const rowSelection = this.props.tableData.rowSelection ? Selection : null
    return (
      <div>
        <Table
          {...tableList}
          size={this.state.size}
          rowKey={(record, index) => `${record.onlyKey}`}
          bordered
          dataSource={this.state.data}
          rowSelection={rowSelection}
          columns={columns}
          scroll={this.props.tableData.scroll}
        >
        </Table>
      </div>
    )
  }
}
// 指定 props 的默認(rèn)值:
TableComponent.defaultProps = {

};
TableComponent.propTypes = { //.propTypes是react規(guī)定的名稱,不可以修改
  tableData: PropTypes.shape({
    url: PropTypes.string.isRequired, // 路徑類型
    rowSelection: PropTypes.bool, // 復(fù)選標(biāo)識(shí)
    lineIndex: PropTypes.bool, // 序號(hào)標(biāo)識(shí)
    columns: PropTypes.array.isRequired, // 列參數(shù)
    dataToOut: PropTypes.bool, // 數(shù)據(jù)外傳標(biāo)識(shí)
    addParams: PropTypes.object, // 新增參數(shù)
    size: PropTypes.oneOf(['default', 'middle', 'small']), // 表格尺寸
    handleOverflow: PropTypes.bool, // 全局溢出處理婶博,不需要再單獨(dú)每個(gè)列設(shè)置(設(shè)置后忽略單獨(dú)設(shè)置)
    falseData: PropTypes.array, // 假數(shù)據(jù)
    method: PropTypes.oneOf(['get', 'post']), // 請(qǐng)求方式
    changePageParam:PropTypes.objectOf(function(propValue, key, componentName, location, propFullName) {
      let allowKeys = [ 'pageSize', 'page', 'totalCount', 'list' ]
      if (allowKeys.indexOf(key) < 0 ) { 
        return new Error(
          'Invalid prop `' + componentName + '` supplied to' +
          ' `' + propFullName + '`. Validation failed.'
        );
      }
    }), // 替代頁(yè)面參數(shù)
    scroll: PropTypes.object, // 滾動(dòng)配置
  }),

  // 列新參數(shù)說(shuō)明(由于不知道怎么設(shè)置tableData.columns的參數(shù)類型,
  // 所以暫放在這荧飞,但組件沒(méi)有這個(gè)參數(shù))
  Columns: PropTypes.shape({
    overflow: PropTypes.bool, // 列移除處理(移除顯示省略號(hào)...)
  })
};

export default TableComponent;

作為一個(gè)初級(jí)前端工作者凡人,歡迎大家對(duì)我的代碼、思路進(jìn)行指導(dǎo)叹阔,謝謝大家挠轴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市耳幢,隨后出現(xiàn)的幾起案子岸晦,更是在濱河造成了極大的恐慌,老刑警劉巖睛藻,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件启上,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡店印,警方通過(guò)查閱死者的電腦和手機(jī)冈在,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)按摘,“玉大人包券,你說(shuō)我怎么就攤上這事§畔停” “怎么了溅固?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)照激。 經(jīng)常有香客問(wèn)我发魄,道長(zhǎng),這世上最難降的妖魔是什么俩垃? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任励幼,我火速辦了婚禮,結(jié)果婚禮上口柳,老公的妹妹穿的比我還像新娘苹粟。我一直安慰自己,他們只是感情好跃闹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布嵌削。 她就那樣靜靜地躺著,像睡著了一般望艺。 火紅的嫁衣襯著肌膚如雪苛秕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天找默,我揣著相機(jī)與錄音艇劫,去河邊找鬼。 笑死惩激,一個(gè)胖子當(dāng)著我的面吹牛店煞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播风钻,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼顷蟀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了骡技?” 一聲冷哼從身側(cè)響起鸣个,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎布朦,沒(méi)想到半個(gè)月后毛萌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喝滞,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年阁将,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片右遭。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡做盅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窘哈,到底是詐尸還是另有隱情吹榴,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布滚婉,位于F島的核電站图筹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜远剩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一扣溺、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓜晤,春花似錦锥余、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至足画,卻和暖如春雄驹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背淹辞。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工医舆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人桑涎。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓彬向,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親攻冷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子娃胆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容