table多表头和select

一.React方式:

import React from 'react';
import { Select, Button } from 'antd';
const { Option } = Select;
interface Props {
  width: string | number;
  bordered: string | number;
}
interface State {
  trs: any;
  columns: any;
  selectOption: any;
}
class ImportExcel extends React.Component<Props, State> {
  constructor(props) {
    super(props);
    this.state = {
      trs: [], //tr的集合
      selectOption: [
        { key: '1', value: 'lucy' },
        { key: '2', value: 'lucy11' },
      ],
      columns: [
        //后端返回数据
        {
          name: '姓名',
          key: 'name',
          type: 1,
          subItem: null,
        },
        {
          name: '年龄',
          key: 'age',
          type: 2,
          subItem: [
            {
              name: '看书',
              key: 'age111',
              subItem: null,
              type: 1,
            },
            {
              name: '打球',
              key: 'placeport',
              subItem: null,
              type: 1,
              subItem: [
                {
                  name: '看书',
                  key: 'age111',
                  subItem: null,
                  type: 1,
                },
                {
                  name: '打球',
                  key: 'placeport',
                  subItem: null,
                  type: 1,
                },
              ],
            },
          ],
        },
        {
          name: '爱好',
          key: 'like',
          type: 2,
          subItem: [
            {
              name: '看书1111',
              key: 'like1',
              subItem: null,
              type: 1,
            },
            {
              name: '打球',
              key: 'like22222',
              subItem: null,
              type: 1,
            },
            {
              name: '打球',
              key: 'like22222',
              subItem: null,
              type: 1,
            },
          ],
        },
      ],
    };
  }

  componentWillMount() {
    let { columns } = this.state;
    this.foo(columns);
  }

  //对初始化数据进行处理
  foo = (arr, parent) => {
    if (!arr || (arr && !arr.length)) return;
    let arrResult = JSON.parse(JSON.stringify(arr));
    arrResult.map(item => {
      let len = item.subItem ? item.subItem.length : 0;
      item.rank = parent ? parent.rank + 1 : 0;
      if (len) {
        //subItem 存在
        item.rowspan = 1;
        this.foo(item.subItem, item);
      } else {
        //subItem 不存在
        item.colSpan = 1;
      }
      if (parent) {
        //parent的colSpan为subItem的colSpan总和
        parent.colSpan = parent.colSpan ? parent.colSpan : 0;
        parent.colSpan += item.colSpan;
      }
    });
    this.pushTrs(arrResult);
  };

  pushTrs = arr => {
    let { trs } = this.state;
    let rank = arr[0].rank;
    if (trs[rank]) {
      for (let i in arr) {
        trs[rank].push(arr[i]);
      }
    } else {
      trs[rank] = arr;
    }
  };

  //渲染table
  renderTable = () => {
    let { trs } = this.state;
    return trs.map((item: any) => {
      return (
        <tr align="center">
          {item.map((inner: any) => (
            <th
              colSpan={inner.colSpan}
              rowSpan={inner.rowspan ? inner.rowspan : trs.length - inner.rank}
            >
              {inner.name}
            </th>
          ))}
        </tr>
      );
    });
  };

  //渲染select
  renderSelect = () => {
    let { trs, selectOption } = this.state;
    let arr = trs.flat().filter(item => !item.subItem);
    return (
      <tr align="center">
        {arr.map(item => (
          <th colSpan={item.colSpan}>
            <Select
              placeholder="请选择"
              onChange={e => this.handleChange(e, item.key)}
              style={{
                width: '100%',
                minWidth: '120px',
              }}
            >
              {selectOption.map(({ key, value }) => (
                <Option value={key}> {value} </Option>
              ))}
            </Select>
          </th>
        ))}
      </tr>
    );
  };

  //select选择填充数据
  handleChange = (e, key) => {
    let { columns } = this.state;
    columns.forEach(one => {
      //添加新字段 selectValue
      if (one.key === key) one.selectValue = e;
      if (one.subItem && one.subItem.length > 0) {
        one.subItem.forEach(two => {
          if (two.key === key) two.selectValue = e;
        });
      }
      //组装后的数据 columns
      this.props.handleChange && this.props.handleChange(columns);
    });
  };

  render() {
    let { width = 1000, ...rest } = this.props;

    const currentProps = {
      cellSpacing: '0',
      cellPadding: 10,
      border: '1',
      width,
      ...rest,
    };

    return (
      <div>
        <table {...currentProps}>
          <thead>
            {this.renderTable()}
            {this.renderSelect()}
          </thead>
        </table>
      </div>
    );
  }
}

export default ImportExcel;

有待完善...... 粗略版本!

二.Vue方式   

<template>
  <div class="hello">
    <div class="table">
    <table border="1" cellspacing="0" cellpadding="10" width="100%">
      <thead>
        <tr class="firstHead">
          <th :rowspan="!th.subItem&&2" :colspan="th.subItem&&th.subItem.length" v-for="(th,index) in firstTh" :key="index">{{th.name}}</th>
        </tr>
        <tr class="twoHead">
          <th v-for="(th,index) in secondTh" :key="index">{{th.name}}</th>
        </tr>
        </thead>
        <tbody>
          <tr>
            <td v-for="(a,index2) in tdLength" :key="index2">
              <select v-model="tdValList[index2]">
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
              </select>
            </td>
          </tr>
        </tbody>
      </table>
      <button @click="getSubmitData()">获取提交数据</button>
    </div>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
        tableData: [
          {
            name: "姓名",
            subItem: null,
            type: 1
          },
          {
            name: "性別",
            subItem: null,
            type: 1
          },
          {
            name: "教育经历",
            subItem: [
              {
                name: "开始时间",
                subItem: null,
                type: 1
              },
              {
                name: "结束时间",
                subItem: null,
                type: 1
              },
              {
                name: "学校",
                subItem: null,
                type: 1
              },
              {
                name: "学历",
                subItem: null,
                type: 1
              }
            ],
            type: 2
          },
          {
            name: "工作经历",
            subItem: [
              {
                name: "开始时间",
                subItem: null,
                type: 1
              },
              {
                name: "结束时间",
                subItem: null,
                type: 1
              },
              {
                name: "公司",
                subItem: null,
                type: 1
              },
              {
                name: "职位",
                subItem: null,
                type: 1
              }
            ],
            type: 2
          },
          {
            name: "年龄",
            subItem: null,
            type: 1
          }
        ],
        firstTh: [],
        secondTh: [],
        tdValList:[],
        tdLength: 0
    };
  },
  created(){
    this.tableInit();
  },
  methods:{
    tableInit(){
      this.tableData.forEach(val=>{
        if(val.type == 1&&!val.subItem){
          this.tdLength++;
        }else if(val.subItem&&val.type == 2){
          this.tdLength += val.subItem.length;
        }
        this.firstTh.push(val);
        if(val.subItem&&val.type == 2){
          this.secondTh = this.secondTh.concat(val.subItem);
        }
      })

      for(let i = 0;i<this.tdLength;i++){
        this.tdValList.push('');
      }
      
    },
    getSubmitData(){
      console.log(this.tdValList)
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
td,
th {
  font-style: normal;
  font-weight: normal;
  text-align: center;
}

tr {
  height: 48px;
}

.twoHead th {
  width: 6.25%;
  height: 48px;
  padding: 0 10px;
  font-size: 14px;
  font-weight: normal;
}

.firstHead th {
  font-size: 14px;
  font-weight: bold;
}

table {
  border: none;
  border-collapse: collapse;
  border-color: #d8dfe6;
}

table thead {
  background: #f3fdff;
}
</style>

 

posted on 2020-08-29 23:14  旋风小美女  阅读(603)  评论(1)    收藏  举报