Vue 项目实战:全局封装 Element UI 表格组件
在维护中大型后台管理系统时,我们常遇到表格配置重复、样式不统一的问题。与其在每个页面重复编写 el-table 的模板和逻辑,不如将其二次封装为一个全局组件。这样既能保证交互体验的一致性,又能大幅减少样板代码。
核心思路
我们将封装一个名为 NewTable 的组件,它接收 tableOption 作为配置项,内部根据配置动态生成列结构。利用 Vue 2 的 $attrs 透传机制,可以将原生 el-table 的属性直接传递给底层组件,实现高度灵活的控制。
组件实现
首先创建 new-table/index.vue 文件。这里重点处理了表头渲染逻辑,支持索引、多选以及自定义插槽渲染。
<template>
<div class="new_table">
<div class="table_main">
<el-table
ref="table"
:data="tableDataList"
:span-method="objectSpanMethod"
:highlight-current-row="true"
v-bind="$attrs"
border
@selection-change="selectionChange"
v-loading="tableLoading"
style="width: 100%"
>
<template v-for="(col, index) in tableOption.columns">
<!-- 序号列 -->
<template v-if="col.type == 'index'">
<el-table-column
type="index"
:key="index"
:label="col.label || '编号'"
:width="col.width || 50"
align="center"
></el-table-column>
</template>
<!-- 选择列 -->
<template v-if="col.type == 'selection'">
<el-table-column
type="selection"
:key="index"
:width="col.width || 50"
align="center"
></el-table-column>
</template>
<!-- 文本列及自定义渲染 -->
<template v-if="col.type == 'text'">
<template v-if="col.render">
<el-table-column
:key="index"
:show-overflow-tooltip="!!col.overflow"
:align="col.align || 'left'"
:sortable="!!col.sortable"
:prop="col.prop"
:label="col.label"
:width="col.width || ''"
>
<template slot-scope="scope">
<table-render
:render="col.render"
:scope="scope"
:prop="col.prop"
></table-render>
</template>
</el-table-column>
</template>
<template v-else>
<el-table-column
:key="index"
:show-overflow-tooltip="!!col.overflow"
:align="col.align || 'left'"
:sortable="!!col.sortable"
:prop="col.prop"
:label="col.label"
:width="col.width || ''"
></el-table-column>
</template>
</template>
</template>
</el-table>
</div>
</div>
</template>
<script>
export default {
name: 'NewTable',
props: {
tableDataList: {
type: Array,
required: true
},
tableOption: {
type: Object,
default: () => ({})
},
tableLoading: {
type: Boolean,
default: false
}
},
methods: {
// 合并行策略示例
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (rowIndex % 2 === 0) {
return { rowspan: 2, colspan: 1 };
}
return { rowspan: 0, colspan: 0 };
},
// 选中事件处理
selectionChange(val) {
this.$emit('selection-change', val);
}
}
};
</script>
<style scoped>
.new_table {
padding: 10px;
}
.table_main {
background: #fff;
border-radius: 4px;
}
</style>
全局注册与使用
在 main.js 中引入并注册该组件,之后在任何页面直接使用 <new-table> 即可。
import NewTable from '@/components/new-table';
Vue.component('NewTable', NewTable);
使用时只需传入数据源和列配置,无需关心内部细节。这种写法特别适合列表页频繁变更的场景,后续若需调整分页逻辑或加载状态,只需修改封装组件一处即可。
注意事项
- 插槽兼容性:如果业务需要更复杂的自定义列,建议保留
slot-scope并在外部提供默认插槽。 - 属性透传:
v-bind="$attrs"是 Vue 2 的特性,确保父组件传递的class、style等能正确生效。 - 性能优化:当数据量极大时,注意开启虚拟滚动或分页,避免 DOM 节点过多导致卡顿。
通过这种方式,我们不仅统一了团队内的表格风格,还让新成员能快速上手开发,减少了大量重复劳动。

