[组件封装] 使用 el-table 封装一个通用表格组件

[组件封装] 使用 el-table 封装一个通用表格组件

·

2 min read

在做业务时经常会碰到有许多地方都用到表格,并且表格的结构都大致一样,不想每次都重新写一大堆重复的东西,所以这篇博客就总结一下如何使用el-table来封装一个通用的表格组件

明确封装的需求

我的需求主要有以下几点:

  • 在通用表格组件内请求数据

  • 表格的渲染统一在组件内采用v-for的形式

  • 有时需要自定义某些列单元格内的数据展示的形式

  • 不仅仅只是数据展示,同时还要对某些数据进行一些操作

针对需求需要怎样设计

对于以上的几点,需要明确应该如何设计该组件,以及如何在父子组件间进行通信:

  • 由于要在表格内请求数据,那么就应该传入一个url参数,并封装一个统一的请求数据的方法供组件使用

  • 因为要采用v-for的形式渲染,且el-table的数据是按列来渲染的,所以要传入一个colums[]数组,代表每列的字段

  • 因为要自定义某些列单元格的数据,所以应该用具名作用域插槽向父组件传递scope.row的数据

  • 如果想要操作某些数据,可以再手动多加一列,点击后拿到该行的数据,对这些数据做对应的操作即可

大致代码如下

  • 封装统一的get请求:
import { AxiosResponse } from "axios"
import instance from "./instance"// 通用 get 请求
export const commonGetRequest = async <T = any> (url: string) => {
  const res: AxiosResponse<T> = await instance.get<T>(url)
  return res.data
}
  • 通用表格组件CommonTable.vue
<script setup lang="ts">
import { defineProps, onMounted, ref } from "vue"
// 封装统一的 get 请求
import { commonGetRequest } from "@/server/common.ts"// 每一列的字段
interface Column {
  prop: string,
  label: string,
  slotName?: string,
}
​
interface TableProps {
  url: string,
  columns: Column[], // 表格的每一列数组
}
const props = defineProps<TableProps>()
​
// 请求回来的表格数据
const tableData = ref<any>()
​
// 对某一行的数据进行操作
const operate = (data: any) => {
  console.log("该行的数据", data) // 这里输出可以看到拿到的数据
  // 进行后续的操作...
}
​
const getTableData = async () => {
  const { data } = await commonGetRequest(props.url)
  console.log("表格数据", data)
  tableData.value = data
}
​
onMounted(() => {
  getTableData()
})
</script>
​
<template>
  <div class="container">
    <el-table :data="tableData" border style="width: 100%">
      // 根据每一列的数组自动渲染
      <el-table-column v-for="(item, idx) in columns" :key="idx" v-bind="item">
        // 自定义该列的数据渲染
        <template #default="scope">
          // 通过插槽将数据传给父组件,如果没有传,就给一个默认值
          // 根据传入的每一列的 prop 来获取到渲染的数据的字段的内容
          <slot :name="item.slotName" :row="scope.row">{{ scope.row[item.prop] }}</slot>
        </template>
      </el-table-column><!-- 额外添加一行操作 -->
      <el-table-column label="操作">
        <template #default="scope">
          <div style="color: orange; cursor: pointer;" @click="() => operate(scope.row)">操作</div>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
​
<style lang="scss">
​
</style>
​
  • 在父组件中使用:
<script setup lang="ts">
import CommonTable from './components/common-table.vue'// 定义列结构及对应的字段
const abilityColums = [
  {
    label: "产出",
    prop: "generation",
  },
  {
    label: "英文名",
    prop: "nameEn",
  },
  {
    label: "中文名",
    prop: "nameZh",
  },
  {
    label: "日文名",
    prop: "nameJa",
    slotName: "nameJa"
  },
]
</script>
​
<template>
  <CommonTable url="/ability/list" :columns="abilityColums">
    // 通过插槽获取子组件传回来的数据,并进行自定义,再传回给子组件
    <template #nameJa="{ row }">
      <div style="display: flex;">
        <div class="dot"></div>
        {{ row.nameJa }}
      </div>
    </template>
  </CommonTable>
</template>
​
<style lang="scss" scoped>
.dot {
  height: 5px;
  width: 5px;
  border-radius: 100%;
  background-color: orangered;
}
</style>
​