本文已参与「新人创作礼」活动,一起开启掘金创作之路。
elementUI el-table 二次封装
基本能满足绝大部分的需求,利用el-table预留的插槽,在默认插槽和header插槽里面又分别放了插槽,十分灵活,表头和表格内容全部可以自定义,添加的属性不够可以自己加。另外,Table Attributes 和 Table Events 可以直接写在WsTable标签内,降低与业务的耦合。
展示效果:
代码示例: 公共组件(定义为WsTable)
<template>
<el-table
ref="WsTable"
:row-key="getRowKey"
:data="tableData"
v-bind="$attrs"
v-on="$listeners"
>
<el-table-column
v-if="showSelect"
width="50"
type="selection"
reserve-selection
></el-table-column>
<el-table-column
v-if="showIndex"
fixed
label="序号"
width="50"
type="index"
:align="align"
></el-table-column>
<el-table-column
v-for="(col, index) in tableColumns"
:key="col.prop"
:prop="col.label"
:width="col.width"
:align="col.align || align"
:fixed="col.fixed"
:sortable="col.sortable"
:show-overflow-tooltip="col.showOverflowTooltip"
>
<template #header="scope">
<slot :name="col.header" :scope="{ header: col.label, ...scope }">
<span>{{ col.label }}</span>
</slot>
</template>
<template #default="scope">
<slot :name="col.prop" :scope="scope">
<span>{{ scope.row[col.prop] }}</span>
</slot>
</template>
</el-table-column>
// 分页组件插槽
<slot v-show="tableData.length > 10" name="pagination"></slot>
</el-table>
</template>
<script>
export default {
name: "WsTable",
inheritAttrs: false,
props: {
// 表格数据
tableData: {
type: Array,
default: () => [],
require: true,
},
// 表格列和列属性:
// label显示的标题
// align对齐方式
// show-overflow-tooltip当内容过长被隐藏时显示tooltip
tableColumns: {
type: Array,
default: () => [],
require: true,
},
// 是否显示多选框
showSelect: {
type: Boolean,
default: false,
},
// 是否显示索引
showIndex: {
type: Boolean,
default: false,
},
// 对齐方式
align: {
type: String,
default: "center",
},
// 行数据的 Key,用来优化 Table 的渲染
rowKey: {
type: String,
default: "id",
},
},
methods: {
getRowKey(row) {
return row[this.rowKey];
},
// 请求完接口想清空表格所选
clearSelection() {
this.$refs.WsTable.clearSelection();
},
// 对 Table 进行重新布局
doLayout() {
this.$refs.WsTable.doLayout();
},
},
};
</script>
<style></style>
父组件
<template>
<div id="app">
<WsTable
:table-data="tableData"
:table-columns="tableColumns"
show-select
show-index
@selection-change="selectionChange"
>
<template #genderHeader="{ scope }">
<div>
{{ scope.header }}
<div>
<el-select v-model="region" size="mini" placeholder="请选择性别">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="2"></el-option>
<el-option label="未知" value="3"></el-option>
</el-select>
</div>
</div>
</template>
<template #gender="{ scope }">
<div>
{{
+scope.row.gender === 1
? "男"
: +scope.row.gender === 2
? "女"
: "未知"
}}
</div>
</template>
<template #operation>
<div>
<el-button>编辑</el-button>
<el-button>删除</el-button>
</div>
</template>
</WsTable>
</div>
</template>
<script>
import WsTable from "./components/WsTable.vue";
export default {
name: "App",
components: {
WsTable,
},
data() {
return {
region: "",
tableData: [
{
name: "张三张三张三张三张三张三张三张三张三张三张三张三张三",
age: 18,
gender: "1",
},
{
name: "李四",
age: 19,
gender: "2",
},
{
name: "王五",
age: 20,
gender: "3",
},
],
tableColumns: [
{
label: "名称",
prop: "name",
propHeader: "nameHeader",
showOverflowTooltip: true,
},
{
label: "年龄",
prop: "age",
header: "ageHeader",
sortable: true,
width: 100,
},
{ label: "性别", prop: "gender", header: "genderHeader", width: 1000 },
{
label: "操作",
prop: "operation",
header: "operationHeader",
fixed: "right",
width: 200,
},
],
};
},
methods: {
selectionChange(selection) {
console.log('selection', selection)
}
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<style scoped>
#app >>> .el-select .el-input__inner {
text-align: center;
}
</style>