React之表格行/列合並


 

參考鏈接:https://ant.design/components/table-cn/#components-table-demo-colspan-rowspan

參考圖:

實現代碼如下:

import { Table } from 'antd';

// In the fifth row, other columns are merged into first column
// by setting it's colSpan to be 0
const renderContent = (value, row, index) => {
  const obj = {
    children: value,
    props: {},
  };
  if (index === 4) {
    obj.props.colSpan = 0;
  }
  return obj;
};

const columns = [{
  title: 'Name',
  dataIndex: 'name',
  render: (text, row, index) => {
    if (index < 4) {
      return <a href="javascript:;">{text}</a>;
    }
    return {
      children: <a href="javascript:;">{text}</a>,
      props: {
        colSpan: 5,
      },
    };
  },
}, {
  title: 'Age',
  dataIndex: 'age',
  render: renderContent,
}, {
  title: 'Home phone',
  colSpan: 2,
  dataIndex: 'tel',
  render: (value, row, index) => {
    const obj = {
      children: value,
      props: {},
    };
    if (index === 2) {
      obj.props.rowSpan = 2;
    }
    // These two are merged into above cell
    if (index === 3) {
      obj.props.rowSpan = 0;
    }
    if (index === 4) {
      obj.props.colSpan = 0;
    }
    return obj;
  },
}, {
  title: 'Phone',
  colSpan: 0,
  dataIndex: 'phone',
  render: renderContent,
}, {
  title: 'Address',
  dataIndex: 'address',
  render: renderContent,
}];

const data = [{
  key: '1',
  name: 'John Brown',
  age: 32,
  tel: '0571-22098909',
  phone: 18889898989,
  address: 'New York No. 1 Lake Park',
}, {
  key: '2',
  name: 'Jim Green',
  tel: '0571-22098333',
  phone: 18889898888,
  age: 42,
  address: 'London No. 1 Lake Park',
}, {
  key: '3',
  name: 'Joe Black',
  age: 32,
  tel: '0575-22098909',
  phone: 18900010002,
  address: 'Sidney No. 1 Lake Park',
}, {
  key: '4',
  name: 'Jim Red',
  age: 18,
  tel: '0575-22098909',
  phone: 18900010002,
  address: 'London No. 2 Lake Park',
}, {
  key: '5',
  name: 'Jake White',
  age: 18,
  tel: '0575-22098909',
  phone: 18900010002,
  address: 'Dublin No. 2 Lake Park',
}];

ReactDOM.render(<Table columns={columns} dataSource={data} bordered />,
  mountNode);

 實際工作中通過參考該例子實現的效果如圖:

實現代碼如下:

import React from 'react';
import {Table} from 'antd';
import { queryCreditsAndPeriods } from './service';

export default class TotalCreditsAndHoursModal extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: false,
            total: 0,
            dataSource: []
        };
    }

    params = {
        pageNo: 1,
        pageSize: 10,
    }

    componentWillMount() {
        this.queryCreditsAndPeriods();
    }

    // 根據majorId(年級專業方向ID)查詢專業方案下的總畢業學分及學時
    queryCreditsAndPeriods = () => {
        queryCreditsAndPeriods(this.props.majorId, (response) => {
            this.setState({
                dataSource: response
            });
        })
    }

    // 獲取tablebox的ref
    onTableBoxRef = ref => {
        this.tableBoxRef = ref;
    };

    render() {
        const {dataSource} = this.state;

        // 模塊名稱合並計算
        let numObj = {};
        dataSource.map((elem) => {
            let moduleName = elem.schemeModuleName;
            if (moduleName in numObj) {
                numObj[moduleName] += 1
            } else {
                numObj[moduleName] = 1
            }
        })

        // 隸屬類別合並計算
        let numObj3 = {};
        dataSource.map((elem,index) => {
            let  classifyParentName= elem.schemeClassifyParentName;
            if (classifyParentName in numObj3  ) {
                numObj3[classifyParentName] += 1
            } else {
                if(typeof(classifyParentName) === "undefined"){
                    numObj3["undefined"+index] = 1
                }else{
                    numObj3[classifyParentName] = 1
                }
            }
        })

        // 小數點轉百分號的處理函數
        const renderContent = (value) => {
            if (value != undefined && value != null) {
                // 轉為百分比展示
                const scale = Math.round((value * 10000) / 100.00) + '%';
                return scale;
            }
        };

        let mergeObj = []; // 合並所屬類別

        const columns = [
            {
                title: '方案模塊',
                align: 'center',
                dataIndex: 'schemeModuleName',
                key: 'schemeModuleName',
                width: '20%',
                render: (value, row, index) => {
                    const obj = {
                        children: <span style={{fontWeight: 'bold'}}>{value}</span>,
                        props: {}
                    };
                    if (index === dataSource.length-1) {
                        obj.props.colSpan = 3;
                        obj.props.rowSpan = 1;
                    }
                    if ((index > 0 && value !== dataSource[index - 1].schemeModuleName) || index == 0) {
                        obj.props.rowSpan = numObj[value]
                    } else {
                        obj.props.rowSpan = 0;
                    }
                    return obj;
                }
            },
            {
                title: '隸屬類別',
                align: 'center',
                colSpan: 0,
                width: '10%',
                dataIndex: 'schemeClassifyParentName',
                key: 'schemeClassifyParentName',
                render: (value, row, index) => {
                    const obj = {
                        children: value,
                        props: {},
                    };
                    // 只要沒有隸屬類別這一列,則設置colSpan為0
                    if (typeof(value) === 'undefined') {
                        obj.props.colSpan = 0;
                        // 判斷是否是第一個出現,如果是則設置合並指定的行,已出現過同一個的值就不要合並行了,則設置rowSpan為0
                    } else if (mergeObj.indexOf(value) == -1 ){
                        obj.props.rowSpan = numObj3[value];
                        mergeObj.push(value);
                    }else {
                        obj.props.rowSpan = 0;
                    }
                    // 判斷如果是最后一行,則設置rowSpan為0,表格不會渲染
                    if (index === dataSource.length-1) {
                        obj.props.colSpan = 0;
                    }
                    return obj;
                },
            },
            {
                title: '方案類別',
                align: 'center',
                colSpan: 2,
                width: '20%',
                dataIndex: 'schemeClassifyName',
                key: 'schemeClassifyName',
                render: (value, row, index) => {
                    const obj = {
                        children: value,
                        props: {},
                    };
                    // 判斷所屬類別那行的值是否存在,如果不存在則直接設置合並2列
                    if (typeof(dataSource[index].schemeClassifyParentName) === "undefined" ) {
                        obj.props.colSpan = 2;
                    }
                    // 判斷如果是最后一行,則設置rowSpan為0,表格不會渲染
                    if (index === dataSource.length-1) {
                        obj.props.colSpan = 0;
                    }
                    return obj;
                },
            },
            {
                title: '總學分',
                align: 'center',
                width: '10%',
                dataIndex: 'schemeSystemCredit',
                key: 'schemeSystemCredit',
            },
            {
                title: '學分比例',
                align: 'center',
                width: '15%',
                dataIndex: 'creditScale',
                key: 'creditScale',
                render: renderContent,
            },
            {
                title: '總學時',
                align: 'center',
                width: '10%',
                dataIndex: 'schemeSystemPeriod',
                key: 'schemeSystemPeriod',
            },
            {
                title: '學時比例',
                align: 'center',
                width: '15%',
                dataIndex: 'periodScale',
                key: 'periodScale',
                render: renderContent,
            }
        ];

        return (
            <div style={{marginRight:'10px',marginLeft:'20px'}}>
                <Table height={272} columns={columns} dataSource={this.state.dataSource} bordered />
            </div>
        );
    }
}

  總結:不管是合並行還是合並列,只跟要操作的列有關,與表格中的其他列都沒有關系,在處理過程中,主要處理思路是對要合並的列展開。

比如我上圖是想要合並方案模塊,所屬方案類別,方案類別這三列進行合並行/列。

其中

if ((index > 0 && value !== dataSource[index - 1].schemeModuleName) || index == 0) {
                        obj.props.rowSpan = numObj[value]
                    } else {
                        obj.props.rowSpan = 0;
                    }
這里要求的數據格式相同的方案模塊放在一起,這樣便於判斷以及設置合並行數或者列數。這個思想很重要:比如有兩條數據:[{parent:'主干課',children:'科學課'},{parant:'主干課',children:'自然課'}] 解讀:第一次遍歷數據時,通過index == 0 進入obj.props.rowSpan = numObj[value]這個循環內
,第二次,再次判斷第一次的值(
parent)是否跟第二次的值(parent)相等,如果相等,則設置為obj.props.rowSpan = 0;避免重復合並導致錯誤。

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM