封装el-table 基于element封装可配置JSON表格组件

基于element封装可配置JSON表格组件
话不多说直接贴代码,复制运行即可查看效果
在这里插入图片描述
子组件全部代码

<template>
  <div class="custom-table">
    <el-table
      :data="tableData"
      border
      style="width: 100%"
      size="mini"
      max-height="800"
      v-bind="$attrs"
      v-on="$listeners"
      highlight-current-row
    >
      <template v-for="item in config.column">
        <!-- 操作 -->
        <template v-if="item.type === 'handler'">
          <el-table-column
            :key="item.prop"
            v-bind="item"
            align="center"
            fixed="right"
          >
            <template slot-scope="{ row }">
              <el-button
                v-for="btn in item.btns"
                :key="btn.label"
                type="text"
                @click="handelClick($event, btn.click, row)"
                :icon="btn.icon"
              >
                <!-- {{ btn.label }} -->
              </el-button>
            </template>
          </el-table-column>
        </template>
        <!-- 自定义slot -->
        <template v-else-if="item.type === 'custom'">
          <el-table-column :key="item.prop" v-bind="item" align="center">
            <template slot-scope="scope">
              <slot :name="item.slotName" v-bind="scope" :prop="item.prop" />
            </template>
          </el-table-column>
        </template>
        <!-- 默认 -->
        <template v-else>
          <el-table-column
            :key="item.prop"
            v-bind="item"
            align="center"
            :show-overflow-tooltip="true"
          />
        </template>
      </template>
    </el-table>
    <!-- 分页 -->
    <el-pagination
      v-if="config.usePagination"
      background
      small
      layout="prev, pager, next"
      style="text-align: center; margin-top: 10px"
      :current-page="config.paginationData.currentPage"
      :page-size="config.paginationData.pageSize"
      :total="config.paginationData.total"
      @current-change="handleCurrentChange"
    >
    </el-pagination>
  </div>
</template>

<script>
export default {
  props: {
    config: {
      type: Object,
      default() {
        return {
          column: [],
          paginationData: {
            pageSize: 20,
            currentPage: 1,
            total: 0,
          },
        };
      },
      required: true,
    },
    tableData: {
      type: Array,
      default() {
        return [];
      },
    },
  },
  mounted() {
    console.log(this.config, "config");
  },
  methods: {
    handelClick(e, click, row) {
      e.stopPropagation();
      this.$emit(click, row);
    },
    handleCurrentChange(val) {
      this.$emit("currentChange", val);
    },
  },
};
</script>

<style lang="scss" scoped></style>

父组件使用

<template>
  <div>
    <el-button @click="getData">data</el-button>
    <CustomTable
      size="mini"
      v-loading="loading"
      :config="tableConfig"
      :table-data="tableData"
      @row-click="handleRowClick"
      @selection-change="selectionChange"
      @handelEditClick="handelEditClick"
      @handelTeamEditClick="handelTeamEditClick"
      @deleteItemClick="deleteItemClick"
      @currentChange="handleCurrentChange"
    >
      <template #inputEdit="{ row }">
        <el-input
          v-model="row.inputValue"
          placeholder="please input"
          size="small"
        ></el-input>
      </template>
      <template #artcleName="{ row }">
        <el-tag v-for="item in row.artcleName" :key="item.id" size="small">
          {{ item.name }}
        </el-tag>
      </template>
    </CustomTable>
  </div>
</template>

<script>
import tableConfig from "./config";
import CustomTable from "@/components/CustomTable/index.vue";

export default {
  components: {
    CustomTable,
  },
  data() {
    return {
      loading: false,
      tableConfig,
      tableData: [
        {
          id: 1,
          text: "test",
          title: "test",
          admin: "guanliyuan ",
          category: "小白",
          inputValue: "Context",
          artcleName: [
            { id: 1, name: "Context" },
            { id: 2, name: "标签" },
          ],
        },
      ],
    };
  },
  created() {
    this.tableData = this.generateRandomData(50);
    this.tableConfig.paginationData.total = this.tableData.length;
  },
  methods: {
    getData() {
      console.log(this.tableData, "表格数据");
    },
    generateRandomData(count) {
      const categories = ["小白", "中级", "高级", "专家", "初学者"];
      const admins = ["guanliyuan", "administrator", "admin", "user", "tester"];
      const texts = ["test", "example", "sample", "demo", "testcase"];
      const titles = [
        "Test Title",
        "Example Title",
        "Sample Title",
        "Demo Title",
        "Testcase Title",
      ];

      const randomElement = (arr) =>
        arr[Math.floor(Math.random() * arr.length)];
      const randomString = (length) =>
        Math.random()
          .toString(36)
          .substring(2, length + 2);

      return Array.from({ length: count }, (_, index) => ({
        id: index + 1,
        text: randomElement(texts),
        title: randomElement(titles),
        admin: randomElement(admins),
        category: randomElement(categories),
        inputValue: randomString(8),
        artcleName: Array.from({ length: 2 }, (_, nameIndex) => ({
          id: nameIndex + 1,
          name: randomString(5),
        })),
      }));
    },
    handleRowClick(val) {
      console.log(val, "点击行");
    },
    selectionChange(val) {
      console.log(val, "勾选");
    },
    handelEditClick(row) {
      console.log(row, "编辑");
    },
    handelTeamEditClick(row) {
      console.log(row, "团队编辑");
    },
    deleteItemClick(row) {
      console.log(row, "删除");
    },
    handleCurrentChange(val) {
      this.tableConfig.paginationData.currentPage = val;
      console.log(val, "当前页");
    },
  },
};
</script>

可配置文件 js
放置同级位置
在这里插入图片描述

const tableConfig = {
  //type 区分操作类型  normal:普通  handler:操作  custom:自定义插槽
  column: [
    { type: "selection", width: 60, align: "center" },
    {
      type: "normal",
      prop: "text",
      label: "KeyWords",
      width: 200,
    },
    { type: "normal", prop: "title", label: "Title" },
    {
      type: "normal",
      prop: "category",
      label: "Category",
      width: 150,
    },
    {
      type: "normal",
      prop: "admin",
      label: "Admin",
      width: 200,
    },
    {
      type: "handler",
      label: "Controls",
      width: 150,
      btns: [
        {
          label: "Edit",
          click: "handelEditClick",
          icon: "el-icon-edit",
        },
        {
          label: "TeamEdit",
          click: "handelTeamEditClick",
          icon: "el-icon-s-open",
        },
        {
          label: "Delete",
          click: "deleteItemClick",
          icon: "el-icon-delete",
        },
      ],
    },
    {
      type: "custom",
      label: "Input",
      prop: "inputValue",
      slotName: "inputEdit",
    },
    {
      type: "custom",
      label: "artcleName",
      prop: "artcleName",
      slotName: "artcleName",
    },
  ],
  usePagination: true,
  paginationData: {
    pageSize: 20,
    currentPage: 1,
    total: 0,
  },
};

export default tableConfig;
  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值