ts二次封装element-ui的table表格,带loading,分页
新建文件tablePage.vue
<template>
<div id="table_page">
<el-table
ref="vtable"
v-loading="loading"
@row-click="rowClick"
@select="select"
@select-all="select"
@current-change="rowChange"
@selection-change="handleSelectionChange"
:data="data"
size="mini"
stripe
style="width: 100%"
highlight-current-row
:header-cell-style="headerStyle"
:cell-style="cellStyle"
:row-style="rowStyle"
>
<el-table-column
v-if="selection"
type="selection"
width="55">
</el-table-column>
<template v-for="(item,index) in column">
<el-table-column
v-if="!item.slot"
:key="index"
:prop="item.prop"
:width="item.width"
:label="item.label"
:align="item.align || 'center'"
:fixed="item.fixed"
>
</el-table-column>
<el-table-column
v-if="item.slot"
:key="index"
:label="item.label"
:prop="item.prop"
:width="item.width"
:fixed="item.fixed"
:align="item.align || 'center'">
<template #default="{ row, $index }">
<slot :name="item.slot" :index="$index" :row="row" :value="row[item.prop]" :prop="item.prop"></slot>
</template>
</el-table-column>
</template>
</el-table>
<el-pagination
v-if="page"
@current-change="handleCurrentChange"
layout="total, prev, pager, next"
:current-page.sync="page.PageIndex"
:total="page.PageTotal"
:page-size="page.PageSize">
</el-pagination>
</div>
</template>
<script lang="ts">
import { Component, Vue, Prop } from "vue-property-decorator"
import { Table } from 'element-ui'
@Component({
props: {
data: {
type: Array,
required: true
},
selection: {
type: Boolean,
},
column: {
type: Array,
required: true
},
height: {
type: String
},
page: {
required: true,
type: [Object, Boolean],
default: function() {
return {
PageIndex: 20,
PageTotal: 0,
PageSize: 1
}
}
},
rowStyle: {
type: [Function, Object],
default: function() {
return {}
}
},
cellStyle: {
type: [Function, Object],
default: function() {
return {}
}
},
headerStyle: {
type: [Function, Object],
default: function() {
return {
backgroundColor: "rgb(221, 221, 221)",
color: "black"
}
}
},
index: {
type: Boolean,
default: false
},
check: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
},
rowClick: {
type: Function,
default: function(){}
},
},
components: {
}
})
export default class TablePage extends Vue {
public handleCurrentChange(val: number) {
this.$emit("page", val);
console.log(val)
}
public select(selection: object[], row:object) {
this.$emit("select", selection, row);
}
public clear(){
(this.$refs["vtable"] as Table).clearSelection();
}
public toggle(){
(this.$refs["vtable"] as Table).toggleAllSelection();
}
public rowChange(selection: object[], row:object){
this.$emit("rowChange", selection, row);
}
public handleSelectionChange(selection: object[]){
this.$emit("handleSelectionChange", selection);
}
}
</script>
<style scoped>
#table_page {
/* height: 100%; */
}
/* #table_page .el-table {
height: calc(100% - 50px);
} */
#table_page .el-table {
position: relative;
margin-bottom: 33px;
}
#table_page .el-pagination {
float: right;
position: fixed;
bottom: 0;
z-index: 10;
right: 0;
background: #fff;
text-align: right;
border-top: 1px solid #eee;
width: 100%;
}
</style>
依次解释:
v-loading:对表格添加加载效果。
@row-click:当某一行被点击时会触发该事件。
@select:当用户手动勾选数据行的 Checkbox 时触发的事件
@select-all:当用户手动勾选全选 Checkbox 时触发的事件
@current-change:当表格的当前行发生变化的时候会触发该事件,可以拿到用户当前选中的行数据(无checkbox情况下)。如果要高亮当前行,请打开表格的 highlight-current-row 属性
@selection-change:当选择项发生变化时会触发该事件,选中checkbox和取消时都会触发,可以用来获取用户选中的数据。
:data:数组
stripe:是否为斑马纹 table
highlight-current-row:是否要高亮当前行
:header-cell-style:表头单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有表头单元格设置一样的 Style。
:cell-style:单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有单元格设置一样的 Style。
:row-style:行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。
实例:
import vtable from "@/components/common/TablePage.vue";
components: {
vtable
}
<vtable
ref="vtable"
:page="page"
@page="pageChange"
v-loading="loading"
:data="tableData"
@select="changeList"
:selection="true"
:column="column"
:headerStyle="{background: '#fff'}"
>
</vtable>
ts部分:
//初始化page,Models是我管理interface接口校验的文件,在这里也粘一下
// 分页interface
export interface Page {
PageIndex: number
PageTotal: number
PageSize: number
}
//分页初始化数据,这里可以与后端约定返回的字段名称
private page: Models.Page = {
PageIndex: 1,
PageTotal: 0,
PageSize: 20
};
//
public pageChange(e: number) {
//拿到用户点击的页码
this.page.PageIndex = e;
console.log(e);
//nextPage是封装好的方法,也粘出来
// 获取下一页页数
//export const nextPage = (curPage: number, pageSize: number) => {
//return (curPage - 1) * pageSize
//}
//searchForm是el-form的表单数据对象,是做列表筛选功能
this.searchForm.skipCount = nextPage(e, this.page.PageSize);
//更新列表
this.getProductList();
}
//Loading效果使用
private async getProductList() {
this.loading = true;
try {
let res = await GetMixedProducts.request(this.searchForm);
this.tableData = res.items;
if (res.items) {
this.page.PageTotal = res.totalCount!;
}
} catch (error) {
} finally {
this.loading = false;
}
}
//勾选数据行时触发
private changeList(selection: Models.Product[], row: Models.Product) {
this.checkList = [];
selection.forEach(element => {
this.checkList.push(element.id);
});
}
//方便理解,把product粘出来
// 商品列表 node
export interface Product {
name: string
productNumber: string
saleName: string
displayOrder: number
isPublished: boolean
productCoverThumbPictureUrl: string
isPortal: boolean
stockQuantity: number
hasProductPrice: boolean
usedForMaintenance: boolean
isComobo: boolean
id: string
}
//column
private readonly column = [
{
label: "商品图片",
slot: "productCoverThumbPictureUrl",
width: 140
},
{
label: "产品名称",
prop: "name"
},
{
label: "商品名称",
prop: "saleName"
},
{
label: "商品编号",
prop: "productNumber",
width: 120
},
{
label: "是否销售商品",
slot: "isPortal",
width: 120
},
{
label: "是否服务配件",
slot: "usedForMaintenance",
width: 120
},
{
label: "是否套装商品",
slot: "isComobo",
width: 120
},
{
label: "显示顺序",
prop: "displayOrder",
width: 120
},
{
label: "上架状态",
slot: "isPublished",
width: 120
},
{
label: "操作",
slot: "operate",
width: 180
}
];
大致就这样,能提高table复用率,写的不太好,欢迎提问。slot插槽也可以举一个实例:
<template #isPublished="{ row }">
<span v-if="row.isPublished === true">已上架</span>
<span v-else-if="row.isPublished === false">未上架</span>
<span v-else>未创建</span>
</template>