在项目开发中,使用表格展示数据是最常见的需求,对于成千上万的数据来说渲染会造成浏览器渲染加载慢或者是卡顿甚至浏览器崩溃。
对于element-ui表格一次性加载10000条数据会导致浏览器卡顿或者崩溃, 这里使用vxe Table 解决渲染卡顿问题,官网网址:https://vxetable.cn/v3/#/start/install
npm install vxe-pc-ui@3.3.1 vxe-table@3.11.2
# 或者
yarn add vxe-pc-ui@3.3.1 vxe-table@3.11.2
# 或者
pnpm add vxe-pc-ui@3.3.1 vxe-table@3.11.2
// ...
import VxeUI from 'vxe-pc-ui'
import 'vxe-pc-ui/lib/style.css'
import VxeUITable from 'vxe-table'
import 'vxe-table/lib/style.css'
// ...
Vue.use(VxeUI)
Vue.use(VxeUITable)
// ...
npm install vxe-table@3.11.2
# 或者
yarn add vxe-table@3.11.2
# 或者
pnpm add vxe-table@3.11.2
// ...
import VxeUITable from 'vxe-table'
import 'vxe-table/lib/style.css'
// ...
Vue.use(VxeUITable)
// ...
为了复用封装成一个独立的table带分页的组件
<template>
<div class="tab-container">
<div class="table-box" style="padding: 0;">
<vxe-table
:data="data"
:scroll-x="{ enabled: true, gt: 0 }"
:scroll-y="{ enabled: true, gt: 0, mode: 'wheel' }"
:column-config="{ resizable: true }"
class="vxe-table"
height="100%"
show-overflow
stripe
show-header-overflow
show-footer-overflow
border
align="center"
@checkbox-all="handleSelectionChange"
@checkbox-change="handleSelectionChange">
<vxe-column v-if="isSelection" type="checkbox" width="60"/>
<vxe-column v-if="isTableIndex" type="seq" width="60"/>
<template v-for="item in columns">
<vxe-column v-if="item.isShow" :key="item.fieldCode" :field="item.fieldCode" :title="item.fieldName">
<template #default="{ row }">
<span v-if="item.onclick" class="underLine" @click="item.onclick(row)">{{ fieldValueByRowRenderer(row, item) }}</span>
<span v-else>{{ row[item.fieldCode] ? fieldValueByRowRenderer(row, item) : '-' }}</span>
</template>
</vxe-column>
</template>
<vxe-column v-if="filterRowButtons().length > 0" :width="rowButtonsWidth" label="操作" fixed="right" align="center">
<template #default="{ row }">
<div v-if="filterRowButtons(row).length <= 3">
<template v-for="(item, index) in filterRowButtons(row)">
<el-button v-has="item.permission" v-if="isShowButton(item, row)" :key="index" type="text" @click="item.click(row)">{{ item.label }}</el-button>
</template>
</div>
<div v-else>
<el-button v-has="filterRowButtons(row)[0].permission" v-if="isShowButton(filterRowButtons(row)[0], row)" type="text" @click="filterRowButtons(row)[0].click(row)">{{ filterRowButtons(row)[0].label }}</el-button>
<el-button v-has="filterRowButtons(row)[1].permission" v-if="isShowButton(filterRowButtons(row)[1], row)" type="text" @click="filterRowButtons(row)[1].click(row)">{{ filterRowButtons(row)[1].label }}</el-button>
<el-dropdown trigger="click">
<span class="el-dropdown-link">更多<i class="el-icon-caret-bottom el-icon--right" /> </span>
<el-dropdown-menu slot="dropdown" class="dropDown">
<el-dropdown-item class="clearfix">
<template v-for="(item, index) in filterRowButtons(row).filter((el, index) => index > 1)">
<el-button v-has="item.permission" v-if="isShowButton(item, row)" :key="index" type="text" @click="item.click(row)">{{ item.label }}</el-button>
</template>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
</vxe-column>
</vxe-table>
</div>
<div class="pagination">
<el-pagination
:current-page="currPage"
:page-size="pageSize"
:page-sizes="pageSizes"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@current-change="handlePageChange"
@size-change="handleSizeChange"
/>
</div>
</div>
</template>
<script>
import store from '@/store'
export default {
name: 'Table',
props: {
// 是否加载中
isLoading: {
type: Boolean,
default: false
},
// 表格序号
isTableIndex: {
type: Boolean,
default: false
},
// 表格复选框
isSelection: {
type: Boolean,
default: false
},
// 当前页
currPage: {
type: Number,
default: 1
},
// 每页条数
pageSize: {
type: Number,
default: 10
},
// 总条数
total: {
type: Number,
default: 0
},
// 分页条数
pageSizes: {
type: Array,
default: () => [10, 50, 100, 300, 500, 1000, 8000]
},
// 表格数据
data: {
type: Array,
default: () => []
},
// 表头数据
columns: {
type: Array,
default: () => []
},
rowButtonsWidth: {
type: Number,
default: 120
},
// 行按钮
rowButtons: {
type: Array,
default: () => []
}
},
computed: {
// 过滤没有权限的 和按钮不显示的数据
filterRowButtons() {
// 系统所有的按钮权限
const userPermissions = store.getters && store.getters.userPermissions
return (row) => {
if (!row) return this.rowButtons
this.rowButtons.forEach(item => {
if (item.isShow && typeof item.isShow === 'function') {
item.isFlag = item.isShow(row)
} else {
item.isFlag = item.isShow
}
})
return this.rowButtons.filter(item => {
if (item.permission) {
return userPermissions.includes(item.permission) && item.isFlag
} else {
return item.isFlag
}
})
}
}
},
methods: {
// 带表格列格式化的值
fieldValueByRowRenderer(row, columnConfig) {
if (!columnConfig || typeof columnConfig.fieldTableRowRenderer != 'function') {
return row[columnConfig.fieldCode]
}
return columnConfig.fieldTableRowRenderer(row)
},
// 是否展示按钮
isShowButton(item, row) {
if (typeof item.isShow === 'function') {
return item.isShow(row)
} else {
return item.isShow
}
},
// 选中的值
handleSelectionChange(val) {
this.$emit('selectionChange', val)
},
handlePageChange(val) {
this.$emit('pageChange', val)
},
handleSizeChange(val) {
this.$emit('sizeChange', val)
},
doLayout() {
this.$nextTick(() => {
this.$refs.table.doLayout()
})
}
}
}
</script>
<style scoped lang="scss">
.tab-container {
display: flex;
flex-direction: column;
flex: 1;
}
.table-box {
display: flex;
flex-direction: column;
flex: 1;
.vxe-table {
flex: 1;
}
.pagination {
height: 44px;
}
}
.underLine {
color: #5887fb;
cursor: pointer;
}
.underLine:hover {
text-decoration: underline;
color: #799ffc;
}
.el-dropdown-link{
margin-left:5px;
color: #5887fb;
font-size: 12px;
}
.el-dropdown-menu__item:focus, .el-dropdown-menu__item:not(.is-disabled):hover {
background-color: transparent;
color: transparent;
}
::v-deep.table-box .vxe-table--header-wrapper {
background-color: rgb(22, 93, 255, 0.15) !important;
}
</style>
<template>
<bigDataTable
:data="tableData"
:columns="columns"
:row-buttons="rowButtons"
:is-selection="true"
:is-table-index="true"
:curr-page="query.currPage"
:page-size="query.limit"
:total="pageTotal"
:is-loading="loading"
@selectionChange="handleSelectionChange"
@pageChange="handlePageChange"
@sizeChange="handleSizeChange" />
</template>
<script>
export default {
data() {
return {
columns: [
{
fieldName: '客户名称', // 表格头
fieldCode: 'companyName', // 字段名
minWidth: 120,
isShow: true,
selectShow: 1
// fieldTableRowRenderer: (row) => { // 处理当前行数据
// return 2
// },
// onclick: (row) => { // 当前字段点击事件
// console.log(row)
// }
}
...
],
rowButtons: [
{
label: '审核',
permission: '', // 权限码
isShow: (row) => { // 按钮是否显示 数据类型 boolean 和 function
return true
},
click: this.click // 行按钮操作事件
},
]
}
}
}
</script>
说明: