useVxeTable VxeTable 工具
vxe-table 是很好用的 vue 表格,但在使用时可能需要进一步封装,这里提供轻量的工具,方便使用。
未使用状态
<template>
<vxe-grid ref="gridRef" v-bind="gridOptions"> </vxe-grid>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { reactive } from 'vue'
import { type VxeGridProps } from 'vxe-table'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
border: true,
loading: false,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: false,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 100, fixed: 'left' },
{ title: '列0', field: 'col0', width: 100 },
{ title: '列1', field: 'imgUrl', width: 100 },
{ title: '列2', field: 'col2', width: 300 },
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{ title: '列6', field: 'col6', width: 200 },
{ title: '列7', field: 'col7', width: 200 },
{ title: '列8', field: 'col8', width: 200, fixed: 'right' },
],
data: [],
})
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(50)
</script>
<style>
/* 无关代码,为修复文档通用样式造成的影响 */
.vp-doc .vxe-grid table,
.vp-doc .vxe-grid td,
.vp-doc .vxe-grid th {
margin: initial;
border: initial;
padding: initial;
overflow-x: initial;
}
.vitepress-demo-preview__element-plus__container:has(.vxe-grid) {
overflow: initial;
}
</style>
表头吸附、滚动条吸附(未开启虚拟滚动)
配置 sticky:true
<template>
<vxe-grid ref="gridRef" v-bind="gridOptions" class="top-64"> </vxe-grid>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { reactive, ref } from 'vue'
import { type VxeGridProps } from 'vxe-table'
import { useVxeTable } from '@x-anything/hooks'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
border: true,
loading: false,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: false,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 100, fixed: 'left' },
{ title: '列0', field: 'col0', width: 100 },
{ title: '列1', field: 'imgUrl', width: 100 },
{ title: '列2', field: 'col2', width: 300 },
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{ title: '列6', field: 'col6', width: 200 },
{ title: '列7', field: 'col7', width: 200 },
{ title: '列8', field: 'col8', width: 200, fixed: 'right' },
],
data: [],
})
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(50)
const gridRef = ref()
useVxeTable(gridRef, {
sticky: true,
})
</script>
<style>
.top-64 .vxe-table--header-wrapper {
top: 64px !important;
}
</style>
表头吸附、滚动条吸附(开启虚拟滚动)
配置 virtualSticky:true
TIP
由于 vxe-table 会监测自身及父元素的高度变化来设置虚拟高度,如果直接设置表格或其父元素高度会导致滚动时虚拟高度异常,来回跳,闪现空白,所以使用 virtualSticky 时请提供两层祖先元素,useVxeTable 会将父父元素作为粘性定位的窗口,父元素作为粘性定位的元素,从而不改变表格自身,避免负面影响
<template>
<div>
<div>
<vxe-grid ref="gridRef" v-bind="gridOptions" class="top-64"> </vxe-grid>
</div>
</div>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { computed, reactive, ref } from 'vue'
import { type VxeGridProps } from 'vxe-table'
import { useVxeTable } from '@x-anything/hooks'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
height: computed(() => window.innerHeight) as any,
border: true,
loading: false,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: true,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 100, fixed: 'left' },
{ title: '列0', field: 'col0', width: 100 },
{ title: '列1', field: 'imgUrl', width: 100 },
{ title: '列2', field: 'col2', width: 300 },
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{ title: '列6', field: 'col6', width: 200 },
{ title: '列7', field: 'col7', width: 200 },
{ title: '列8', field: 'col8', width: 200, fixed: 'right' },
],
data: [],
})
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(50)
const gridRef = ref()
useVxeTable(gridRef, {
virtualSticky: true,
})
</script>
<style>
.top-64 .vxe-table--header-wrapper {
top: 64px !important;
}
</style>
大量复杂列
目前 vxetable 在存在冻结列的情况下渲染速度较慢,在有大量列时容易出现白屏;并且为了提高性能,左右及中间滚动存在防抖处理,在滚动时会有延时错位的感觉。
<template>
<x-button @click="handleOpenDialog">打开弹窗(为避免样式污染)</x-button>
<Teleport to="body">
<dialog id="largeClumnsdialog">
<div>
<x-button @click="loadData(5000)">加载5k条</x-button>
<x-button @click="loadData(10000)">加载1w条</x-button>
<x-button @click="loadData(30000)">加载3w条</x-button>
<vxe-grid v-bind="gridOptions">
<template #buttonSlot>
<x-tooltip title="tooltip">
<x-button>按钮</x-button>
</x-tooltip>
</template>
</vxe-grid>
</div>
<x-button @click="handleCloseDialog">关闭</x-button>
</dialog>
</Teleport>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { reactive } from 'vue'
import { type VxeGridProps } from 'vxe-table'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
showOverflow: true,
border: true,
loading: false,
height: 600,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: true,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 80, fixed: 'left' },
{
title: '列0',
fixed: 'left',
children: [
{ title: '列1', field: 'imgUrl', width: 80 },
{ title: '列2', field: 'col2', width: 80 },
],
},
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列7',
fixed: 'right',
children: [
{ title: '列9', field: 'col9', width: 80 },
{ title: '列10', field: 'col10', width: 80 },
],
},
{ title: '列8', field: 'col8', width: 80, fixed: 'right' },
],
data: [],
})
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(200)
// 不相关代码,传送到body下为避免样式污染造成的虚拟滚动错位
const handleOpenDialog = () => {
const dialog = document.getElementById(
'largeClumnsdialog'
) as HTMLDialogElement
dialog.showModal()
}
const handleCloseDialog = () => {
const dialog = document.getElementById(
'largeClumnsdialog'
) as HTMLDialogElement
dialog.close()
}
</script>
相比之下 v4.7.59 等低版本(不支持自适应行高)在相同的情况下基本不会白屏。(codesandbox 中可尝试修改两种版本比较)
打开 codesandbox(4.7.59 版本 vxetable)
如果开启了自适应行高性能会进一步下降
<template>
<x-button @click="handleOpenDialog">打开弹窗(为避免样式污染)</x-button>
<Teleport to="body">
<dialog id="largeClumnsAutoRowHeightDialog">
<div>
<x-button @click="loadData(5000)">加载5k条</x-button>
<x-button @click="loadData(10000)">加载1w条</x-button>
<x-button @click="loadData(30000)">加载3w条</x-button>
<vxe-grid v-if="show" v-bind="gridOptions">
<template #buttonSlot>
<x-tooltip title="tooltip">
<x-button>按钮</x-button>
</x-tooltip>
</template>
</vxe-grid>
</div>
<x-button @click="handleCloseDialog">关闭</x-button>
</dialog>
</Teleport>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { reactive, ref } from 'vue'
import { type VxeGridProps } from 'vxe-table'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
border: true,
loading: false,
height: 600,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: true,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 100, fixed: 'left' },
{
title: '列0',
fixed: 'left',
children: [
{ title: '列1', field: 'imgUrl', width: 100 },
{ title: '列2', field: 'col2', width: 200 },
],
},
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列7',
fixed: 'right',
children: [
{ title: '列9', field: 'col9', width: 80 },
{ title: '列10', field: 'col10', width: 80 },
],
},
{ title: '列8', field: 'col8', width: 80, fixed: 'right' },
],
data: [],
})
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(200)
// 不相关代码,传送到body下为避免样式污染造成的虚拟滚动错位
const show = ref(false)
const handleOpenDialog = () => {
const dialog = document.getElementById(
'largeClumnsAutoRowHeightDialog'
) as HTMLDialogElement
dialog.showModal()
show.value = true
}
const handleCloseDialog = () => {
const dialog = document.getElementById(
'largeClumnsAutoRowHeightDialog'
) as HTMLDialogElement
dialog.close()
}
</script>
采用原生 sticky 来固定左右列
在没有固定列的情况下性能会好很多,useVxeTable 提供原生粘性定位固定列,配置 colSticky:true
,如果有列宽拖动还需绑定 resizableChange
。
性能会比自带固定列好点,不会错位
<template>
<x-button @click="handleOpenDialog">打开弹窗(为避免样式污染)</x-button>
<Teleport to="body">
<dialog id="largeClumnsStickyDialog">
<div>
<x-button @click="loadData(5000)">加载5k条</x-button>
<x-button @click="loadData(10000)">加载1w条</x-button>
<x-button @click="loadData(30000)">加载3w条</x-button>
<vxe-grid
ref="gridRef"
v-bind="gridOptions"
@resizable-change="resizableChange"
>
<template #buttonSlot>
<x-tooltip title="tooltip">
<x-button>按钮</x-button>
</x-tooltip>
</template>
</vxe-grid>
</div>
<x-button @click="handleCloseDialog">关闭</x-button>
</dialog>
</Teleport>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { reactive, ref, toRef } from 'vue'
import { type VxeGridProps } from 'vxe-table'
import { useVxeTable } from '@x-anything/hooks'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
showOverflow: true,
border: true,
loading: false,
height: 600,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: false,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 80, fixed: 'left' },
{
title: '列0',
fixed: 'left',
children: [
{ title: '列1', field: 'imgUrl', width: 80 },
{ title: '列2', field: 'col2', width: 80 },
],
},
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列7',
fixed: 'right',
children: [
{ title: '列9', field: 'col9', width: 80 },
{ title: '列10', field: 'col10', width: 80 },
],
},
{ title: '列8', field: 'col8', width: 80, fixed: 'right' },
],
data: [],
})
const gridRef = ref()
const { resizableChange } = useVxeTable(gridRef, {
colSticky: true,
})
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(100)
// 不相关代码,传送到body下为避免样式污染造成的虚拟滚动错位
const handleOpenDialog = () => {
const dialog = document.getElementById(
'largeClumnsStickyDialog'
) as HTMLDialogElement
dialog.showModal()
}
const handleCloseDialog = () => {
const dialog = document.getElementById(
'largeClumnsStickyDialog'
) as HTMLDialogElement
dialog.close()
}
</script>
采用原生 sticky 来固定左右列(开启虚拟滚动)
目前 4.8.x 版本白屏问题比较严重,待官方优化
如果开启虚拟滚动还需绑定 cellStyle
<template>
<x-button @click="handleOpenDialog">打开弹窗(为避免样式污染)</x-button>
<Teleport to="body">
<dialog id="largeClumnsStickyVirtualDialog">
<div>
<x-button @click="loadData(5000)">加载5k条</x-button>
<x-button @click="loadData(10000)">加载1w条</x-button>
<x-button @click="loadData(30000)">加载3w条</x-button>
<vxe-grid
ref="gridRef"
v-bind="gridOptions"
@resizable-change="resizableChange"
>
<template #buttonSlot>
<x-tooltip title="tooltip">
<x-button>按钮</x-button>
</x-tooltip>
</template>
</vxe-grid>
</div>
<x-button @click="handleCloseDialog">关闭</x-button>
</dialog>
</Teleport>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { reactive, ref, toRef } from 'vue'
import { type VxeGridProps } from 'vxe-table'
import { useVxeTable } from '@x-anything/hooks'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
showOverflow: true,
border: true,
loading: false,
height: 600,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: true,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 80, fixed: 'left' },
{
title: '列0',
fixed: 'left',
children: [
{ title: '列1', field: 'imgUrl', width: 80 },
{ title: '列2', field: 'col2', width: 80 },
],
},
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列7',
fixed: 'right',
children: [
{ title: '列9', field: 'col9', width: 80 },
{ title: '列10', field: 'col10', width: 80 },
],
},
{ title: '列8', field: 'col8', width: 80, fixed: 'right' },
],
data: [],
})
const gridRef = ref()
const { resizableChange, cellStyle } = useVxeTable(gridRef, {
colSticky: true,
})
gridOptions.cellStyle = cellStyle
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(100)
// 不相关代码,传送到body下为避免样式污染造成的虚拟滚动错位
const handleOpenDialog = () => {
const dialog = document.getElementById(
'largeClumnsStickyVirtualDialog'
) as HTMLDialogElement
dialog.showModal()
}
const handleCloseDialog = () => {
const dialog = document.getElementById(
'largeClumnsStickyVirtualDialog'
) as HTMLDialogElement
dialog.close()
}
</script>
完整功能
<template>
<div>
<x-button @click="loadData(5000)">加载5k条</x-button>
<x-button @click="loadData(10000)">加载1w条</x-button>
<x-button @click="loadData(30000)">加载3w条</x-button>
<div>
<div>
<vxe-grid
class="top-64"
ref="gridRef"
v-bind="gridOptions"
@resizable-change="resizableChange"
>
<template #buttonSlot>
<x-tooltip title="tooltip">
<x-button>按钮</x-button>
</x-tooltip>
</template>
</vxe-grid>
</div>
</div>
</div>
</template>
<script lang="tsx" setup>
import { VxeGrid } from 'vxe-table'
import 'vxe-table/styles/all.scss'
import { reactive, ref, toRef, computed } from 'vue'
import { type VxeGridProps } from 'vxe-table'
import { useVxeTable } from '@x-anything/hooks'
interface RowVO {
id: number
[key: string]: string | number | boolean | any[]
}
const gridOptions = reactive<VxeGridProps<RowVO>>({
border: true,
loading: false,
height: computed(() => window.innerHeight) as any,
columnConfig: {
resizable: true,
},
scrollY: {
enabled: true,
gt: 0,
},
columns: [
{ type: 'checkbox', width: 80, fixed: 'left' },
{
title: '列0',
fixed: 'left',
children: [
{ title: '列1', field: 'imgUrl', width: 80 },
{ title: '列2', field: 'col2', width: 80 },
],
},
{ title: '列3', field: 'col3', width: 300 },
{ title: '列4', field: 'col4', width: 300 },
{ title: '列5', field: 'col5', width: 300 },
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列6',
field: 'col6',
width: 200,
slots: {
default: 'buttonSlot',
},
},
{
title: '列7',
fixed: 'right',
children: [
{ title: '列9', field: 'col9', width: 80 },
{ title: '列10', field: 'col10', width: 80 },
],
},
{ title: '列8', field: 'col8', width: 80, fixed: 'right' },
],
data: [],
})
const gridRef = ref()
const { resizableChange, cellStyle } = useVxeTable(gridRef, {
virtualSticky: true,
colSticky: true,
})
gridOptions.cellStyle = cellStyle
// 模拟行数据
const loadData = (rowSize: number) => {
gridOptions.loading = true
setTimeout(() => {
const dataList: RowVO[] = []
for (let i = 0; i < rowSize; i++) {
const item: RowVO = {
id: 10000 + i,
imgUrl:
i % 3 === 0
? 'https://vxeui.com/resource/img/546.gif'
: 'https://vxeui.com/resource/img/673.gif',
}
for (let j = 0; j < 10; j++) {
if (i % 9 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容9内容9 内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9内容9 内容9内容9内容9 内容9内容9`
} else if (i % 8 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容8内容8内容8内容8`
} else if (i % 7 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容7内容7`
} else if (i % 6 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容6内容6内容6内容6内容6内容6内容6内容6`
} else if (i % 5 === 0) {
item[`col${j}`] = `值_${i}_${j} 内容5内容5内容5内容5内容5`
} else if (i % 4 === 0) {
item[
`col${j}`
] = `值_${i}_${j} 内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4内容4`
} else {
item[`col${j}`] = `值_${i}_${j}`
}
}
dataList.push(item)
}
gridOptions.data = dataList
gridOptions.loading = false
}, 350)
}
loadData(200)
</script>