在做业务时经常会碰到有许多地方都用到表格,并且表格的结构都大致一样,不想每次都重新写一大堆重复的东西,所以这篇博客就总结一下如何使用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>