在Vue项目中,我们经常需要使用表格来展示数据。为了提高代码复用性和开发效率,我们可以封装一个全局表格组件,方便在各个页面中使用。本文将介绍如何使用Vue和TypeScript来实现这个全局表格组件。
功能需求
我们的全局表格组件需要具备以下功能:
- 可以接受表格数据作为组件的props
- 表格支持排序和分页功能
- 表格支持自定义列和操作按钮
- 表格支持多选和单选功能
实现思路
我们可以使用element-ui提供的Table组件来实现表格的排序和分页功能,使用slot来实现自定义列和操作按钮,使用v-model来实现多选和单选功能。在实现过程中,我们需要注意以下几点:
- 表格数据应该使用Prop的方式传递到组件中,而不是使用组件内部的数据来处理。
- 表格的分页和排序功能应该由父组件来控制,当分页或排序状态改变时,父组件应该更新数据并传递给表格组件。
- 多选和单选功能应该使用v-model来实现,以便父组件能够获取选中的数据。
代码实现
<template>
<el-table
:data="tableData"
:height="height"
:max-height="maxHeight"
:stripe="stripe"
:border="border"
:fit="fit"
:show-header="showHeader"
:highlight-current-row="highlightCurrentRow"
:row-class-name="rowClassName"
:row-style="rowStyle"
:cell-class-name="cellClassName"
:cell-style="cellStyle"
:header-row-class-name="headerRowClassName"
:header-row-style="headerRowStyle"
:header-cell-class-name="headerCellClassName"
:header-cell-style="headerCellStyle"
:row-key="rowKey"
:empty-text="emptyText"
:default-sort="defaultSort"
:tooltip-effect="tooltipEffect"
:tooltip-align="tooltipAlign"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange">
<slot></slot>
</el-table>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { Table } from 'element-ui';
@Component({
components: { Table }
})
export default class GlobalTable extends Vue {
@Prop({ required: true })
private tableData!: any[]; // 表格数据
@Prop({ default: 0 })
private height!: number; // 表格高度
@Prop({ default: 0 })
private maxHeight!: number; // 表格最大高度
@Prop({ default: false })
private stripe!: boolean; // 是否为斑马纹表格
@Prop({ default: false })
private border!: boolean; // 是否带有边框
@Prop({ default: true })
private fit!: boolean; // 是否自动适应父元素宽度
@Prop({ default: true })
private showHeader!: boolean; // 是否显示表头
@Prop({ default: false })
private highlightCurrentRow!: boolean; // 是否高亮当前行
@Prop({ default: '' })
private rowClassName!: string; // 行的类名
@Prop({ default: {} })
private rowStyle!: object; // 行的样式
@Prop({ default: '' })
private cellClassName!: string; // 单元格的类名
@Prop({ default: {} })
private cellStyle!: object; // 单元格的样式
@Prop({ default: '' })
private headerRowClassName!: string; // 表头行的类名
@Prop({ default: {} })
private headerRowStyle!: object; // 表头行的样式
@Prop({ default: '' })
private headerCellClassName!: string; // 表头单元格的类名
@Prop({ default: {} })
private headerCellStyle!: object; // 表头单元格的样式
@Prop({ default: '' })
private rowKey!: string; // 行的key值
@Prop({ default: '暂无数据' })
private emptyText!: string; // 无数据时显示的文本
@Prop({ default: {} })
private defaultSort!: object; // 默认排序
@Prop({ default: 'dark' })
private tooltipEffect!: string; // tooltip主题
@Prop({ default: 'bottom-start' })
private tooltipAlign!: string; // tooltip对齐方式
private handleSortChange(sort: any) {
this.$emit('sort-change', sort);
}
private handleSelectionChange(selection: any) {
this.$emit('selection-change', selection);
}
}
</script>
使用方法
在使用全局表格组件时,只需要在需要使用表格的地方引用该组件即可。使用时需要传递表格数据和其他相关属性作为组件的props。
<template>
<div>
<global-table
:table-data="tableData"
:height="400"
:max-height="500"
:stripe="true"
:border="true"
:fit="true"
:show-header="true"
:highlight-current-row="true"
:row-class-name="rowClassName"
:row-style="rowStyle"
:cell-class-name="cellClassName"
:cell-style="cellStyle"
:header-row-class-name="headerRowClassName"
:header-row-style="headerRowStyle"
:header-cell-class-name="headerCellClassName"
:header-cell-style="headerCellStyle"
:row-key="rowKey"
:empty-text="emptyText"
:default-sort="defaultSort"
:tooltip-effect="tooltipEffect"
:tooltip-align="tooltipAlign"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange">
<!-- 自定义列和操作按钮的slot -->
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" size="small">编辑</el-button>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-table-column>
</global-table>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import GlobalTable from '@/components/GlobalTable.vue';
@Component({
components: { GlobalTable }
})
export default class App extends Vue {
private tableData = [
{ name: '张三', age: 18, address: '上海市' },
{ name: '李四', age: 22, address: '北京市' },
{ name: '王五', age: 30, address: '广州市' },
];
private rowClassName(row: any, index: number) {
return index % 2 === 0 ? 'even-row' : 'odd-row';
}
private rowStyle(row: any, index: number) {
return index % 2 === 0 ? { background: '#f4f4f4' } : {};
}
private cellClassName({ row, column, rowIndex, columnIndex }: any) {
return row.name === '张三' ? 'special-cell' : '';
}
private cellStyle({ row, column, rowIndex, columnIndex }: any) {
return row.name === '张三' ? { background: '#ffcccc' } : {};
}
private headerRowClassName(column: any, columnIndex: number) {
return columnIndex === 0 ? 'first-column' : '';
}
private headerRowStyle(column: any, columnIndex: number) {
return columnIndex === 0 ? { background: '#f2f2f2' } : {};
}
private headerCellClassName({ column, columnIndex }: any) {
return column.label === '地址' ? 'special-header' : '';
}
private headerCellStyle({ column, columnIndex }: any) {
return column.label === '地址' ? { background: '#ccffcc' } : {};
}
private rowKey(row: any) {
return row.name;
}
private defaultSort = {
prop: 'age',
order: 'descending'
};
private tooltipEffect = 'light';
private tooltipAlign = 'top-start';
private handleSortChange(sort: any) {
console.log(sort);
}
private handleSelectionChange(selection: any) {
console.log(selection);
}
}
</script>
总结
通过封装全局表格组件,我们可以大大提高代码复用性和开发效率。在实现过程中,我们需要注意将表格数据作为props传递到组件中,并且将分页和排序等状态控制在父组件中。同时,使用v-model来实现多选和单选功能,以便父组件能够获取选中的数据。希望本文能够对大家在Vue项目中封装全局组件有所帮助。