全新的table组件,vue3+element Plus
-
- [全新的table组件,vue3+element Plus](#全新的table组件,vue3+element Plus)
- tableList.vue文件
-
全新的table组件,vue3+element Plus
tableList.vue文件
javascript
复制代码
<template>
<el-table
ref="tableComRef"
:data="tableData"
:stripe="stripe"
style="width: 100%; height: 100%"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange"
@cell-click="handleCellClick"
@cell-dblclick="handleCellDblClick"
>
<!-- 使用计算属性简化模板逻辑 -->
<el-table-column
v-if="hasSelectionColumn"
type="selection"
width="50">
</el-table-column>
<el-table-column
v-for="(item, index) in displayColumns"
:key="item?.property || item?.prop || index"
:index="indexMethod"
:width="item?.width"
align="center"
:property="item?.property || item?.prop"
:type="item?.type"
:label="item?.label || item?.name"
:sortable="item?.sortable"
:show-overflow-tooltip="true"
:fixed="item?.fixed"
>
<template #default="scope">
<!-- 添加具名插槽支持 -->
<slot :name="item?.property || item?.prop" :row="scope.row" :index="scope.$index" :column="scope.column">
<div v-if="item?.render" class="center h-[100%]" v-html="item?.render(scope.row)"></div>
<!-- 添加对自定义事件的支持 -->
<div v-else-if="item?.renderWithEvent" class="center h-[100%]">
<component
:is="item?.renderWithEvent?.component || 'div'"
v-bind="item?.renderWithEvent?.props ? item?.renderWithEvent?.props(scope.row) : {}"
@[item?.renderWithEvent?.eventType]="item?.renderWithEvent?.handler ? item?.renderWithEvent?.handler(scope.row) : null"
>
{{ item?.renderWithEvent.text ? item?.renderWithEvent?.text(scope.row) : '' }}
</component>
</div>
<!-- 默认显示 -->
<div v-else>
{{ scope.row[item?.property || item?.prop] }}
</div>
</slot>
</template>
<!-- 操作栏 -->
<template v-if="item?.custom" #default="scope">
<div class="operationAll center cursor-pointer">
<!-- 每一列操作项需要根据数据的某些字段展示不同项 -->
<div class="center flex-1 cursor-pointer">
<slot name="operation" :row="scope.row" :index="scope.$index"></slot>
</div>
</div>
</template>
</el-table-column>
</el-table>
</template>
<script setup>
import { ref, computed } from 'vue';
const props = defineProps({
tableHeaderList: {
type: Array,
default: () => [],
},
tableData: {
type: Array,
default: () => [],
},
showTooltip: {
type: Boolean,
default: false,
},
pages: {
type: Object,
default: {
pageSize: 10,
currentPage: 1,
},
},
stripe: {
type: Boolean,
default: false,
},
});
const tableComRef = ref();
const page = computed(() => props.pages);
// 计算属性简化模板逻辑
const hasSelectionColumn = computed(() => {
return props.tableHeaderList.length > 0 && props.tableHeaderList[0]?.type === 'selection';
});
const displayColumns = computed(() => {
if (hasSelectionColumn.value) {
return props.tableHeaderList.slice(1);
}
return props.tableHeaderList;
});
const emits = defineEmits();
// 排序切换方法,在对应列上点击排序时触发
const handleSortChange = (column, prop, order) => {
emits('tableSortChange', column, prop, order);
};
// 列数据勾选时触发
const handleSelectionChange = (selection) => {
emits('tableSelectionChange', selection);
};
let timer = null;
const clickCount = ref(0);
// 当某个单元格被点击时会触发该事件
const handleCellClick = (row, column, cell, event) => {
clickCount.value++;
event.stopPropagation(); // 阻止事件冒泡
timer = setTimeout(() => {
if (clickCount.value === 1) {
clearTimeout(timer);
if (!column.property || column.property === '') return; // 点击的是操作按钮时不做额外处理
emits('tableCellClick', row, column, cell, event);
} else {
if (!column.property || column.property === '') return; // 点击的是操作按钮时不做额外处理
emits('tableCellDblClick', row, column, cell, event);
}
clickCount.value = 0;
}, 500);
};
// 当某个单元格被双击时会触发该事件
const handleCellDblClick = (row, column, cell, event) => {
clearTimeout(timer);
if (!column.property || column.property === '') return; // 点击的是操作按钮时不做额外处理
emits('tableCellDbClick', row, column, cell, event);
};
// 初始化tableindex
const indexMethod = (index) => {
return page.value.pageSize * (page.value.currentPage - 1) + (index + 1);
};
defineExpose({
tableComRef,
});
</script>
<style scoped>
:deep(.el-scrollbar__view) {
height: 100%;
}
:deep(td.el-table__cell) {
border: 1px solid #f0f0f0;
}
:deep(tr th) {
border-bottom: 1px solid #f0f0f0;
border-right: 1px solid #f0f0f0;
}
:deep(.el-table__cell) {
border-right: 1px solid #f0f0f0;
z-index: inherit;
}
:deep(th) {
height: 50px;
color: #2b3a5a;
background-color: #ebf3ff;
border: 1px solid #f0f0f0;
}
</style>
使用方式
template部分
javascript
复制代码
<tableList
:tableHeaderList="tableHeaderList"
:data="tableData"
@table-cell-click="handleTableCellClick"
>
<template #secondDistributionScene="{ row, index }">
<el-image style="width: 100px; height: 100px" :src="url" :zoom-rate="1.2" :max-scale="7" :min-scale="0.2"
:preview-src-list="srcList" show-progress :initial-index="0" fit="cover"/>
</template>
<template #operation="{ row, index }">
<p
style="color: rgb(57, 150, 252)"
class="pointer"
@click="toDetails(row, index)"
>
详情
</p>
</template>
</tableList>
js部分
javascript
复制代码
// 表头
const tableHeaderList = ref([
{
label: '短剧基础信息',
prop: 'playletName',
align: 'center',
render: (val) => {
const html = `<div class="startX pointer" style="width: 100%;">
<img src=${val.coverImage || defaultImage} style="display:block;width:30px;height:30px;" @click="handleClick(val)" />
<p style="margin-left: 10px;width:70%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">${val.playletName}</p>
</div>`;
return html;
},
renderWithEvent: {
component: 'div',
text: (row) => row.id,
eventType: 'click',
handler: (row) => showDom(row.id)
}
},
{
label: '观看',
prop: 'totalViews',
align: 'center',
},
{
label: '收藏',
prop: 'totalCollects',
align: 'center',
sortable: true,
},
{
label: '分享',
prop: 'totalShares',
align: 'center',
sortable: true,
},
{
label: '付费剧集解锁人数',
prop: 'totalPayers',
align: 'center',
sortable: true,
},
{
label: '分账收益',
prop: 'copyrightIncome',
align: 'center',
sortable: true,
},
{
label: '分销人数',
prop: 'totalDistributors',
align: 'center',
sortable: true,
},
{
label: '操作',
prop: '',
align: 'center',
custom: true,
},
]);
示例效果