最近使用Vue + element 开发项目,遇到table 表头、内容都需要处理一下在显示的情况 比较复杂,使用element-ui 的 el-table-column如下:

<el-table-column
                    align="center"
                    fixed="right"
            		width="120"
                    label="操作">
              <template slot-scope="scope">
              // 注:这里进行自定义处理显示的内容
                <el-button size="mini" @click="todetail(scope.row)" type="danger">demo</el-button>
              </template>
            </el-table-column>

尽管已经能自定义了但是,还是不满足需求,于是就写了一个高度自定义的table,代码如下:

.vue页面
<template>
<div v-if="ShowTable" style="margin-top: 20px">
 <column :header="Column" :data="tableData" @SelectionChange="mhandleSelectionChange" @tablePrint="todetail"></column>
</div>
</template>
<script>
import  column from 'column.js'
</script>	
column.js文件
export default {
  name: 'column',
  data() {
    return {
      a: {},
      lengthall: 0,
      Count: 0
    }
  },
  props: {
    data: {  // 表格内容数据
      type: Array
    },
    header: {}  // 表头数据
  },
  render(h) {  // table渲染
    let _this = this
    return h('el-table', {
      props: {
        data: this.data,
      },
      on: {  // table的事件
        'selection-change': function (val) {
          _this.handleSelectionChange(val)
        }
      },
      style: {
        width: '100%'
      }
    }, [h('el-table-column', {  // 左侧多选,根据需求增加
      props: {
        type: 'selection',
        width: '55',
        align: 'center',
        fixed: 'left',
      }
    }),
      h('el-table-column', {   // 右侧操作
        props: {
          fixed: 'right',
          label: '操作',
          width: '100',
          align: 'center'
        },
        style: {
          fontSize: '12px',
          color: '#409eff'
        },
        scopedSlots: {   // 表头对应的内容, 里面可根据需求自定义
          default: scope => {
            return h('el-button', {
              props: {
                type: 'danger',
                size: 'small'
              },
              class: 'printCla',
              on: {
                click: function (e) {
                  _this.$emit('tablePrint', scope.row)
                }
              }
            }, '操作')
          }
        }
      }),
      ...this.render(h, this.header),
    ]);
  },
  methods: {
    renderv(h, data) {
      return this.render(h, data)
    },
    render(h, data) {  // 重点:渲染表头的核心处理   (根据需求自定义)
      const _this = this
      _this.a = _this.data;
      var column = []
      for (var i in data) {
        var child = []
        let p = i
        if (data[i].child && Object.keys(data[i].child).length > 0) {
          child = _this.render(h, data[i].child)
          column.push(h('el-table-column', {
            props: {
              label: data[i].label + '&' + data[i].remark,
              align: 'center',
              renderHeader: function (row, column) {
                return _this.submitHeader(row, column)
              }
            },
          }, child))
        } else {
          column.push(h('el-table-column', {
            props: {
              label: data[i].label + '&' + data[i].remark,
              align: 'center',
              prop: data[i].prop,
              renderHeader: function (row, column) {
                return _this.submitHeader(row, column)
              }
            },
            scopedSlots: { 
              default: scope => {
                let imgObj = scope.row.photo
                let mkey = scope.column.property
                return h('span', {
                  props: {},
                }, [
                  h('el-popover', {
                    props: {
                      placement: 'top-start',
                      width: '200',
                      trigger: 'hover',
                      disabled: imgObj && Object.keys(imgObj).length > 0 && imgObj[mkey] ? false : true
                    }
                  }, [
                    h('img', {
                      attrs: {
                        src: imgObj && Object.keys(imgObj).length > 0 && imgObj[mkey] ? imgObj[mkey] : '',
                      },
                      style: {
                        width: '100%',
                        height: 'auto',
                      }
                    }),
                    h('span', {
                      slot: 'reference',
                      trigger: 'hover',
                      style: {fontSize: '12px', color: '#606266'}
                    }, scope.row[data[p].prop]),
                  ]),
                ], scope.row[data[p].prop])
              }
            }
          }))
        }
      }
      return column
    },
    submitHeader(h, row) {  // 处理table 表头的自定义函数
      let Str = null
      let remark = row.column.label.split('&')
      if (remark[0] && remark[0].indexOf('_') > 0 && remark[0].split('_').length > 1) {
        Str = []
        let arr = remark[0].split('_')
        let ColArr = ['#409EFF', '#F56C6C', '#E6A23C', '#909399']
        for (let item in arr) {
          Str.push(
              h('div', {
                style: {
                  color: ColArr[item],
                  lineHeight: '20px',
                  display: 'block',
                  padding: '0',
                  transform: arr.length - 1 == item ? 'scale(0.9)' : 'scale(1)'
                },
              }, arr[item]),
          )
        }
      } else {
        Str = remark[0]
      }
      return (
          h('span', [
            h('span', {slot: 'reference', trigger: 'hover', style: {fontSize: '12px', color: '#409EFF'}}, Str),
            h('el-popover', {
              props: {
                placement: 'top-start',
                width: '200',
                trigger: 'hover',
                content: remark[1] ? remark[1] : '暂无描述信息',
              }
            }, [
              h('i', {
                slot: 'reference',
                class: 'el-icon-question',
                style: {
                  display: remark[1] ? 'inline-block' : 'none'
                },
              }, '')
            ]),
          ])
      )   
    },
    handleSelectionChange(val) {
      this.$emit('SelectionChange', val)  // 可以根据需求自定义事件  ,引入的vue的界面处理
    },
  }
}

@table头部: 可多级嵌套 ,鼠标移动到具体字段位置可弹窗(相当于一个容器 可以填标签、element组件、调整样式) 。
鼠标移动到问好处弹出提示
@table内容:也可自定义,(相当于一个容器 可以填标签、element组件、调整样式)。

以下是我写的demo仅供参考, 取需要用的地方

在这里插入图片描述

总结:

  1. table渲染用column.js文件写的,.vue文件引入使用就行。
  2. table头部自定义 使用el-table-column中的render-header 里面的处理用 render函数渲染
  3. table头部对应的data数据自定义 使用Vue插槽:scopedSlot属性,具体位置见上面demo
  4. Vue 的 render函数、element-ui中的table的render-header 可以好好研究研究,挺灵活的。
  5. 以上为个人总结,仅供参考,欢迎斧正。
Logo

前往低代码交流专区

更多推荐