动态表格与合并

下面是动态表格的vue写法(未使用改变list的方法):

 <el-table
      ref="table"
      :data="list" 
      :span-method="arraySpanMethod"
      style="width: 100%;"
      border
      :header-cell-style="headerStyle"
    >
      <template v-for="column in columnDef">
        <el-table-column
          :key="column.prop"
          :prop="column.prop"
          :label="column.label"
          align="center"
          fixed
        >
          <template slot-scope="scope">
            <span >
              <span>{{ scope.row[scope.column.property] }} </span>
            </span>
          </template>
        </el-table-column>
      </template>
    </el-table>

list是绑定的表格也即单元格数据,columnDef是表头数据,arraySpanMethod是单元格合并的方法,headerStyle是表头的方法。

columnSpanMethod() {
      // 记录合并单元格的信息
      this.span = [...this.columnDef];
       this.columnDef.map((value, index, array) =>{
         this.span[index] = 1; //将所有的单元格初始值设置为1
         array.forEach((val, i) => {
           if (val.label === value.label && i!== index && !this.spanIndex.includes(i)) {
             this.spanIndex.push(index); //若有重复的将index放入spanIndex数组中
             this.span[index]++; // 记录重复也就是单元格要合并的数量
           }
         })
       })
      this.span.map((value, index, array) => {
          if (value > 1 ) { 
// 将得到的单元格合并数据进行处理,让首个重复单元格保持不变,其余均变成
// 与首个重复单元格的距离,用负数表示容易区分。
            for (let i = index + 1; i < index + value; i++) {
              array[i] = index - i;
            }
          }
      })
    }

这是数据的初始化处理,使用vue时放在created钩子上。

headerStyle({ row, column, rowIndex, columnIndex }) {
      // 若没有要合并的表头就直接返回
      if (this.spanIndex.length < 1 )
        return;
      this.span.map((value, index, array) => {
            // 判断条件为 该表头为首个重复项,则隐藏
          if (value>1 || array[index+1] <1) {
            row[index].colSpan = 0  // 本列表头隐藏
            // 若为最后一个重复项
          else if (value < 1) {
          if (array[index + 1] === 1 || index >= array.length - 1){
            row[index].colSpan = array[index + value] //最后一列表头扩展
          }
      })
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      // 若没有要合并的单元格,直接返回
      if (this.spanIndex.length < 1 )
        return;
        // 当本列数据大于1时,说明是首个单元格
      if (this.span[columnIndex] > 1 ) {
        // 本列数据为空则收缩
        if (['', null, undefined].includes(row[this.columnDef[columnIndex].prop])) {
          return {
            rowspan: 0, // 列扩展
            colspan: 0  // 行扩展
          }
        } else {
        // 本列数据不为空就展开,展开行数为重复但单元格数量
          return {
            rowspan: 1, // 列扩展
            colspan: this.span[columnIndex]  // 行扩展
          }
        }
        // 当本列数据小于1时,说明是次单元格
      } else if (this.span[columnIndex] < 1) {
          for (let i =columnIndex - 1; this.span[i] !== 1; i-- ) {
            // 从上一个数据开始判断,之前数据是否有为空的情况
            if ( i >= 0 && row[this.columnDef[i].prop]){ // 只要有不为空,就收缩
                return {
                  rowspan: 0, // 列扩展
                  colspan: 0  // 行扩展
                }
            }
            // 说明之前的数据全为空或者首个单元格开始重复
            if (i < 0 || this.span[ i - 1 ] === 1 ) { 
                // 本单元格不为空则扩展 
              if ((row[this.columnDef[columnIndex].prop])) {
                return {
                  rowspan: 1, // 列扩展
                  colspan: i < 0 ? this.span[i + 1] :this.span[i]  // 行扩展
                }
               // 本单元格为空则判断是否为最后一个重复单元格: 是就扩展,不是就收缩
              } else if (this.span[columnIndex + 1 ] === 1 ) {
                          return {
                            rowspan: 1, // 列扩展
                            colspan: i < 0 ? this.span[i + 1] :this.span[i]  // 行扩展
                          }
                     } else {
                        return {
                          rowspan: 0, // 列扩展
                          colspan: 0  // 行扩展
                        }
                     }

            }
          }
       
      }
    },

上面两个使用单元格扩展属性来操纵表格展示,更好的方法应该是用数组对象来操纵表格展示,这里只对这两天的内容做一个总结和记录,不推荐使用,下面是整个vue组件页面代码:

<template>
  <div class="app">
    <!--工具栏-->
    <div class="head">
    </div>
    <!--表格渲染-->
    <div class="body">
      <el-row :gutter="15">
      <el-col>
        <el-card class="box-card" shadow="never">
        <div slot="header" class="clearfix">
          <span class="role-span">模版列表</span>
        </div>
    <el-table
      ref="table"
      :data="list"
      :span-method="arraySpanMethod"
      style="width: 100%;"
      border
      :header-cell-style="headerStyle"
    >
      <template v-for="column in columnDef">
        <el-table-column
          :key="column.prop"
          :prop="column.prop"
          :label="column.label"
          align="center"
          fixed

        >
          <template slot-scope="scope">
            <span >
              <span>{{ scope.row[scope.column.property] }} </span>
            </span>
          </template>
        </el-table-column>
      </template>
    </el-table>
        </el-card>
      </el-col>
        </el-row>
    </div>
  </div>
</template>

<script>
export default {
  name: "templateData",
  data() {
    return {
      list: [
        {'name': '李磊', 'sex':'男', 'age': '17',  'school': '洛阳理工' , 'Professional':'数学与应用数学' },
        {'name': '张成', 'sex':'女', 'age': '18',  'school': '桂林电子科技', 'Professional':'应用化学' },
        {'name': '练心', 'sex':'女', 'age': '22',  'school': '江西电子科技', 'Professional':'机械设计制造及其自动化'  },
        {'name': '余玠', 'sex':'男', 'age': '22',  'school': '华南理工', 'Professional':'理论与应用力学'  }
      ],
      columnDef: [
        { label: '姓名', prop: 'name' },
        { label: '性别', prop: 'sex' },
        { label: '年龄', prop: 'age' },
        { label: '学校', prop: 'school' },
        { label: '专业', prop: 'Professional' },
      ],
      spanIndex: [],
      span: []
    };
  },

  created() {
    this.columnSpanMethod();
  },
  methods: {
    show(data) {
      console.log(data)
    },
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      if (this.spanIndex.length < 1 )
        return;
      if (this.span[columnIndex] > 1 ) {
        if (['', null, undefined].includes(row[this.columnDef[columnIndex].prop])) {
          return {
            rowspan: 0, // 列扩展
            colspan: 0  // 行扩展
          }
        } else {
          return {
            rowspan: 1, // 列扩展
            colspan: this.span[columnIndex]  // 行扩展
          }
        }
      } else if (this.span[columnIndex] < 1) {
          for (let i =columnIndex - 1; this.span[i] !== 1; i-- ) {
            // debugger
            if ( i >= 0 && row[this.columnDef[i].prop]){ // 不为空
                return {
                  rowspan: 0, // 列扩展
                  colspan: 0  // 行扩展
                }
            }
            if (i < 0 || this.span[ i - 1 ] === 1 ) {  // 说明之前的数据全为空
              if ((row[this.columnDef[columnIndex].prop])) {
                return {
                  rowspan: 1, // 列扩展
                  colspan: i < 0 ? this.span[i + 1] :this.span[i]  // 行扩展
                }
              } else if (this.span[columnIndex + 1 ] === 1 ) {
                          return {
                            rowspan: 1, // 列扩展
                            colspan: i < 0 ? this.span[i + 1] :this.span[i]  // 行扩展
                          }
                     } else {
                        return {
                          rowspan: 0, // 列扩展
                          colspan: 0  // 行扩展
                        }
                     }
            }
          }
      }
    },
    headerStyle({ row, column, rowIndex, columnIndex }) {
      if (this.spanIndex.length < 1 )
        return;
      this.span.map((value, index, array) => {
       if (value>1 || array[index+1] <1) {
          row[index].colSpan = 0  // 本列表头隐藏
        } else if (value < 1) {
          if (array[index + 1] === 1 || index >= array.length - 1){
            row[index].colSpan = array[index + value] //最后一列表头扩展
          }
        }
      if (this.spanIndex.includes(columnIndex)) {
        return 'display: none';
      }
    },
    unique(arr) {
       return Array.from(new Set(arr))
    },
    columnSpanMethod() {
      this.span = [...this.columnDef];
       this.columnDef.map((value, index, array) =>{
         this.span[index] = 1;
         array.forEach((val, i) => {
           if (val.label === value.label && i!== index && !this.spanIndex.includes(i)) {
             this.spanIndex.push(index);
             this.span[index]++;
           }
         })
       })
      this.span.map((value, index, array) => {
          if (value > 1 ) {
            for (let i = index + 1; i < index + value; i++) {
              array[i] = index - i;
            }
          }
      })
    }
  }
};
</script>
<style lang="scss" scoped>


</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值