动态表格的封装方式

4,400 阅读1分钟

写在最前面

这里只是提供一种想法并提供一些快速实现,实际这些技巧可以用在很多地方,如:动态表单

实现方式简述

  • 通过json定义要显示的列
  • 通过slot实现自定义列
  • 通过require.context实现组件的自动注册,并通过<components is="xxx"></components>, 调用动态注册的组件

优点:

  • 支持通过slot自定义扩展
  • 支持编写vue文件扩展列的显示方式
  • 支持通过json来控制列顺序和哪些列需要显示哪些不需要
  • 能避免封装的table组件越来越复杂

表格实现:

<template>
  <el-table :data="tableData" style="width: 100%" height="100%">
    <el-table-column
      v-for="column in columnList"
      :key="column.prop"
      v-bind="column.columnAttrs"
    >
      <template slot-scope="scope">
        <slot
          v-if="column.type === 'slot'"
          :name="column.slotName"
          :row="scope.row"
        ></slot>
        <components
          v-else
          :row="scope.row"
          :prop="column.prop"
          :config="column"
          :is="`column-${column.type}`"
        ></components>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
const modules = {};
// 将当前目录以及子目录中的index.vue自动注册为组件(require.context是webpack提供的,如果是vite要用vite的方式)
const files = require.context("./", true, /index.vue$/);
files.keys().forEach((item) => {
  const name = item.split("/")[1];
  modules[`column-${name}`] = files(item).default;
});
console.log(modules, "modules");

export default {
  name: "CustomTable",
  components: {
    // 组件动态注册
    ...modules,
  },
  props: {
    tableData: {
      type: Array,
      default: () => [],
    },
    columnList: {
      type: Array,
      default: () => [],
    },
  },
};
</script>

<style scoped></style>

func组件

<template>
  <span>{{ config.call(row, config) }}</span>
</template>

<script>
export default {
  name: "ColumnFunc",
  props: {
    config: {
      type: Object,
    },
    row: {
      type: Object,
    },
  },
};
</script>

<style scoped></style>

text组件:

<template>
  <span>{{ row[config.prop] }}</span>
</template>

<script>
export default {
  name: "ColumnText",
  props: {
    config: {
      type: Object,
    },
    row: {
      type: Object,
    },
  },
};
</script>

<style scoped></style>

调用示例

<template>
  <CustomTable :column-list="columnList" :table-data="tableData">
    <template #operate="{ row }">
      <el-button size="small">删除</el-button>
      <el-button size="small" type="primary" @click="onEdit(row)">
        编辑
      </el-button>
    </template>
  </CustomTable>
</template>

<script>
import CustomTable from "@/components/my-table/CustomTable";
export default {
  name: "CustomTableDemo",
  components: {
    CustomTable,
  },
  data() {
    return {
      columnList: [
        {
          type: "text",
          prop: "name",
          columnAttrs: {
            label: "姓名",
            width: "180",
          },
        },
        {
          type: "text",
          prop: "date",
          columnAttrs: {
            label: "日期",
            width: "180",
          },
        },
        {
          type: "func",
          prop: "sex",
          columnAttrs: {
            label: "性别",
          },
          call: (row) => {
            switch (row.sex) {
              case 1: {
                return "男";
              }
              case 2: {
                return "女";
              }
              default: {
                return "未知";
              }
            }
          },
        },
        {
          type: "slot",
          slotName: "operate",
          prop: "operate",
          columnAttrs: {
            label: "操作",
          },
        },
      ],
      tableData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
          sex: 1,
        },
        {
          date: "2016-05-04",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1517 弄",
          sex: 2,
        },
        {
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1519 弄",
          sex: 3,
        },
      ],
    };
  },
  methods: {
    onEdit(row) {
      console.log(row);
    },
  },
};
</script>

<style scoped></style>

效果

image.png

参考文章

Vue业务组件封装(一)Table表格 - 掘金 (juejin.cn)

『前端工程』—— 封装Vue第三方组件的三板斧 - 掘金 (juejin.cn)