【Vue+Element-UI】Table表格:动态Table

前言

客户需求: 实现动态Table,Table表头定制化展示。
实现思路: 参考Element-UI官方Table表格的写法,对Table进行二次封装。全局使用该组件,方便后期维护。


一、封装动态表格组件

1.父组件

父组件list.vue:

    <div class="text-right mt-5">
      <el-button type="info" icon="el-icon-s-operation" @click="openCustom">列表定制el-button>
      <TagColumn :popover-visible.sync="popoverVisible" :columns="columns" @success="updateColumns" />
    div>
    <TagTable
      ref="tagTable"
      :key="key"
      v-loading="PocManager.queryPocTestApplys.loading"
      :highlight-current-row="true"
      height="calc(100vh - 240px)"
      stripe
      class="mt-5"
      :data-list="gridList"
      :columns="columns"
      @sort-change="sortChange"
      @selection-change="selectionChange"
    >
      <el-table-column slot="before" type="index" label="序号" />
      <el-table-column slot="after" label="操作" width="120px">
        <template slot-scope="scope">
          <el-button type="text" icon="el-icon-edit" @click="openEdit(scope.row)">编辑el-button>
          <el-button type="text" @click="remove(scope.row)">删除el-button>
        template>
      el-table-column>
    TagTable>
	openCustom() {
	  this.popoverVisible = true
	},
	updateColumns(data) {
	  this.columns = data
	  this.popoverVisible = false
	  this.key = this.key + 1
	}

2.子组件

1).子组件tag-table.vue:

<template>
  <div>
    <el-table :data="dataList" v-bind="$attrs" v-on="$listeners">
      <slot name="before" />
      <template v-for="column in columns">
        
        <el-table-column v-if="column.status!=='1'" :key="column.code" :label="column.text" :width="column.width" sortable="custom" :prop="column.code">
          <template slot-scope="scope">
            {{ scope.row[column.code] }}
          template>
        el-table-column>
      template>
      <slot name="after" />
      <slot />
    el-table>
  div>
template>
<script>
export default {
  props: {
    // 表格数据list
    dataList: {
      default: null,
      type: Object,
    },
    // 表格列
    columns: {
      default: null,
      type: Object,
    },
  },
  data() {
    return {
    }
  },
  mounted() {
  },
  methods: {
  },
}
script>

2).子组件tag-column.vue

<template>
  <div class="column-popover">
    <el-popover
      v-model="popoverVisible"
      placement="top"
      width="160"
    >
      <el-checkbox-group v-model="checkedColumns">
        <el-checkbox v-for="column in columns" :key="column.code" :label="column.code">{{ column.text }}el-checkbox>
      el-checkbox-group>
      <div style="text-align: right; margin: 0">
        <el-button size="mini" type="text" @click="cancel">取消el-button>
        <el-button type="primary" size="mini" @click="submit">确定el-button>
      div>
    el-popover>
  div>
template>
<script>
export default {
  props: {
    // 列表定制是否显示
    popoverVisible: {
      type: Boolean,
      default: false,
    },
    // 所有的表格列
    columns: {
      default: null,
      type: Object,
    },
  },
  data() {
    return {
      checkedColumns: [], // 选中的表格列
      columnsOptions: [], // 所有列的code
    }
  },
  computed: {
  },
  watch: {
    columns() {
      if (this.columns) {
        this.columns.forEach(item => {
          this.columnsOptions.push(item.code)
          if (item.status !== '1') this.checkedColumns.push(item.code)
        })
      }
      // console.log('columns()', this.columns, this.checkedColumns, this.columnsOptions)
    }
  },
  methods: {
    cancel() {
      this.$emit('update:popoverVisible', false)
    },
    submit() {
      this.columns.map(item => {
        if (this.checkedColumns.includes(item.code)) item.status = '0' // 显示
        else item.status = '1' // 隐藏
      })
      // console.log(this.checkedColumns, this.columns)
      // this.$emit('update:popoverVisible', false)
      this.$emit('success', this.columns)
    }
  },
}
script>
<style lang="scss" scoped>
.column-popover{
    position: absolute;
    min-width: 150px;
    right: 20px;
}
style>

3.引入

组件内引入
1).批量导出component/index.js

import TagTable from './table/tag-table'
import TagColumn from './column/tag-column'
export {
  TagTable,
  TagColumn
}

2).父组件list.vue

import { TagTable, TagColumn } from '../component'
export default {
  components: { TagTable, TagColumn },
}

全局引入

import TagTable from './table/tag-table'
Vue.component('TagTable', TagTable)
import TagColumn from './table/tag-table'
Vue.component('TagColumn', TagColumn)

4.效果图

【Vue+Element-UI】Table表格:动态Table_第1张图片

二、遇到的问题

1.表头顺序不固定

列表定制切换之后,调整的列显示到最后
【Vue+Element-UI】Table表格:动态Table_第2张图片

解决方案

1.Table设置key:key="key"
2.或问题2的方案可以解决

2.表格首行“序号”跑到最后

在子组件tag-table中为了循环,刚开始在 table 里面放置了 div 标签

,导致列表定制切换之后表格首行“序号”跑到最后了。
在这里插入图片描述

错误示例:

<div v-for="column in columns" :key="column.code">
  
  <el-table-column v-if="column.status!=='1'" :label="column.text" :width="column.width" sortable="custom" :prop="column.code">
    <template slot-scope="scope">
      {{ scope.row[column.code] }}
    template>
  el-table-column>
div>

修改为