“table表格在项目中非常常见,项目基本上都能用到,为了更高效的开发,我们可以将其封装的更为简洁!先来看一下效果”
效果如下:
“表格支持el-table属性大部分属性,也可扩展,提供封装思路”
废话少说上代码
1.封装组件
1.huTable.vue
<template>
<el-table
v-bind="$attrs"
v-on="$listeners"
ref="multipleTable"
:key="key"
v-loading="loading"
:data="tableData"
@cell-dblclick="cellDblclick"
>
<hu-table-column
v-bind="item"
v-for="item in bindTableCol"
:key="item.prop"
@cellDblclick="cellDblclick"
:item="item"
slot=""
>
<template v-if="item.slot" v-slot:[item.slot]="{ row, column, $index }">
<slot
:name="item.slot"
:$index="$index"
:row="row"
:column="column"
></slot>
</template>
</hu-table-column>
</el-table>
</template>
<script>
import huTableColumn from "./huTableColumn.vue";
export default {
name: "HuTable",
components: {
huTableColumn,
},
props: {
// 生成 el-table-column
tableCol: {
type: Array,
default: () => [],
},
// 显示的数据
tableData: {
type: Array,
default: () => [],
},
// 表格 loading
loading: {
type: Boolean,
default: false,
},
},
computed: {
// 兼容之前的属性
bindTableCol() {
function processColumn(item, device) {
// 处理每个列对象,创建一个新对象并复制原对象属性
let processedItem = {
...item,
// 兼容之前属性
prop: item.slot || item.key || item.type,
label: item.label || item.title,
// 修改默认值
align: item.align || "center",
fixed: device === "desktop" ? item.fixed : false,
"show-overflow-tooltip": !(item.showOverflowTooltip === false),
"min-width": item.minWidth || item["min-width"] || 130,
};
// 如果存在子列,递归处理子列
if (item.children) {
processedItem.children = item.children.map((child) =>
processColumn(child, device)
);
}
return processedItem;
}
return this.tableCol.map((item) => processColumn(item, this.device));
},
device() {
return this.$store.getters.device;
},
},
data() {
return {
key: Math.random(),
};
},
methods: {
// 双击单元格触发事件
cellDblclick(row, column, cell, event) {
// 避免点击过快导致多个输入框处于焦点状态
// row[column.property + "Show"] = false;
// 避免点击其他单元格导致表格刷新
// if (!['address'].includes(column.property)) return
// row[column.property + "Show"] = true;
this.updateTable();
this.$emit("cell-dblclick", row, column, cell, event);
},
// 清除 单元格选择
resetShow(row, column) {
setTimeout(() => {
row[column.property + "Show"] = false;
this.updateTable();
}, 100);
},
//更新表格
updateTable() {
this.key = Math.random();
},
// 外部调用 校验方法
verifyTable() {
let verifyCol = this.bindTableCol.filter((e) => e.required);
let soul = {
state: false,
message: "",
};
this.tableData.forEach((element) => {
verifyCol.forEach((col, index) => {
if (!element[col.slot] && element[col.slot] !== 0) {
soul.state = true;
soul.message =
soul.message + `第${1 + index}行,${col.label}不能为空;`;
}
});
});
if (!this.tableData.length && verifyCol.length) {
soul.state = true;
soul.message = "表格未填写";
}
if (soul.state) {
if (soul.message.length > 1000) {
soul.message = soul.message.substring(0, 1000) + "......";
}
this.$modal.msgWarning(soul.message);
}
return soul.state;
},
},
};
</script>
<style scoped></style>
2.huTableColumn.vue
<template>
<el-table-column v-if="item.show !== false" v-bind="$attrs">
<!-- 头部 -->
<template #header>
<el-tooltip
effect="dark"
content="当前列必填"
placement="top"
>
<span v-if="item.required" style="color: red">*</span>
</el-tooltip>
<el-tooltip
effect="dark"
content="当前列双击可编辑"
placement="top"
>
<i v-if="item.edit" class="el-icon-edit-outline"></i>
</el-tooltip>
<span>
{{ item.title }}
</span>
</template>
<!-- 内容 -->
<template v-if="item.slot" v-slot="{ row, column, $index }">
<template v-if="item.function">
<div v-html="item.function(row)"></div>
</template>
<template v-else>
<slot
:name="item.slot"
:$index="$index"
:row="row"
:column="column"
></slot>
</template>
</template>
<template v-if="item.children && item.children.length">
<hu-table-column
v-bind="e"
v-for="e in item.children"
:key="e.prop"
:item="e"
slot=""
>
<template v-if="e.slot" v-slot:[e.slot]="{ row, column, $index }">
<slot
:name="e.slot"
:$index="$index"
:row="row"
:column="column"
></slot>
</template>
</hu-table-column>
</template>
</el-table-column>
</template>
<script>
export default {
name: "huTableColumn",
props: {
item: {
type: Object,
default: () => ({}),
},
},
methods: {
},
};
</script>
<style lang="scss" scoped>
.el-icon-edit {
color: #496dff;
cursor: pointer;
&:hover {
color: #7590fd;
}
}
</style>
注意事项:
1.嵌套表头的时候,多级表头无法使用slot插槽。
2.必须要有key或者slot或者type,并且具有唯一性。
2.使用
需要先在main.js里注册
// 表格组件
import HuTable from "@/components/huTable/huTable"
Vue.component("HuTable", HuTable);
页面使用
<hu-table
:tableData="tableData"
:loading="HuLoading"
@selection-change="handleSelectionChange"
:tableCol="tableCol"
>
<!-- slot插槽使用 -->
<template v-slot:operate="{ row }">
<el-button>按钮</el-button>
</template>
</hu-table>
export default {
data() {
return {
HuLoading: false,
tableCol: [
// 可参考elementui el-table-column属性
{
type: "selection", // type属性参考 el-table
width: "55" // 设定宽度
},
{
title: "序号",
type: "index",
show: false, // 是否显示,默认true
},
{
title: "名称",
key: "name",
minWidth: 100, // 最大宽度
},
{
title: "自定义内容",
function: (item) => {
return item; // 自定义内容 html
},
},
{
title: "操作",
slot: "operate",
fixed: "right", // 是否固定left或者right,默认不固定
width: 200,
},
],
tableData: [
{
name: '张三',
age: 18
},
{
name: '李四'
age: 18
}
]
}
}
}