Element UI动态生成多级表头

seefly 2020年11月03日 338次浏览

Element UI动态生成多级表头

思路:使用事先定义好的表头数据结构,使用Vue组件中的render函数动态渲染

查看全部源码

1、表头数据结构

可以看出,下面的数据结构可以描述多级表头的包含关系,其中name表示列的lableprop就是后端传过来的属性,width对应列宽,exeFun函数代表了当前列的值获取方式,不定义则直接获取原始值。child属性是子表头,可无限扩展。

revealList: [
  {
    name: '性别',
    prop: 'gender',
    width: 100,
    exeFun: row => this.enums.gender.filter(e => e.value === row.gender).map(e => e.label)[0]
  },
  {
    name: '专业技能',
    child: [
      {
        name: '前端',
        child: [
          {
            name: 'JavaScript',
            prop: 'js'
          }
        ]
      },
      {
        name: '后端',
        child: [
          {
            name: 'java',
            child: [
              {
                name: 'nio',
                prop: 'nio'
              },
            ]
          },
          {
            name: '框架',
            child: [
              {
                name: 'SpringBoot',
                prop: 'springboot'
              }
            ]
          }
        ]
      },
    ]
  },
],

2、定义组件

使用render函数,对上面定义的表头数据进行递归渲染

Vue.component('my-col', {
  render(h) {
    return this.render(h, this.col)
  },
  props: {
    col: {}
  },
  data: function () {
    return {}
  },
  methods: {
    render(h, header) {
      let column = [];
      // 如果表头还有子表头
      if (header.child) {
        let child = [];
        for (let i = 0; i < header.child.length; i++) {
          // 递归渲染
          child.push(this.render(h, header.child[i]))
        }
        column.push(h('el-table-column', {
          props: {
            label: header.name,
            align: 'center',
          }
        }, child))
      } else {
        column.push(h('el-table-column', {
          props: {
            // 可以自己追加其他el-table-colum支持的参数
            label: header.name,
            prop: header.prop,
            width: header.width,
            align: 'center',
          },
          scopedSlots: {
            default: scope => {
              let value;
              // 有exeFun优先执行
              if (header.exeFun) {
                value = header.exeFun(scope.row)
              } else {
                value = scope.row[header.prop]
              }
              return h('span', value)
            }
          }
        }))
      }
      return column
    },
  }
});

3、使用方式

  • html
<el-table :data="list" style="width: 100%" size="mini">
  <my-col v-for="(item, index) in revealList" :col="item" :key="index" :prop="item.prop" :label="item.name">   </my-col>
</el-table>
  • vue

    const app = new Vue({
      el: "#app",
      data() {
        return {
          enums: {
            gender: [
              { label: '男', value: '1' },
              { label: '女', value: '2' },
            ]
          },
          list: [
            { gender: '1',  js: '熟练', nio: '了解', basic: '精通', springboot: '熟练' },
          ],
          revealList: [
            //...省略
          ],
        }
      },
      methods: {}
    })
    

其他

这种方式只能应对简单的表格渲染,不能应对需要内嵌组件的方式,所以没有直接定义一个table组件替代el-table,可以在有这种需求的时候自己写el-table-column