如题,本文主要解决前端展示渲染大数据量table数据及导出Excel的问题,主要是通过使用v3版本的vxetable和webworker来实现的。亲测可以表格可渲染30w条数据,可在10s内导出30w条数据Excel。
框架:vue2;
一、安装vxetable
可参考官网:https://vxetable.cn/v3/#/table/start/use
- 安装按需加载的插件
npm install babel-plugin-import -D
- 修改文件 .babelrc 或 babel.config.js
{
"plugins": [
[
"import",
{
"libraryName": "vxe-table",
"style": true // 样式是否也按需加载
}
]
]
}
- main.js中全局按需引入模块
import { VXETable, Icon, Column, Table } from 'vxe-table'
Vue.use(Icon).use(Column).use(Table).use(VXETable)
**这样VXETable就已经在项目中安装注册完成,接下来进行安装vue-worker**
二、安装vue-worker
- 首先安装vue-worker插件;
npm install vue-worker -S
- 在main.js中引入
import VueWorker from 'vue-worker'
Vue.use(VueWorker)
- 引入导出XLSX的包
==这里有两种方式==
第一种方式:在web worker中使用XLSX的外部CDN链接
importScripts('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.15.3/xlsx.core.min.js')
然后就可以在web worker中全局使用XLSX了
第二张方式:将上面👆包的js链接下载到本地,放到项目的public文件夹下,可以再建一个workers文件夹存放,如下
然后再web worker中使用
//importScripts('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.15.3/xlsx.core.min.js')
importScripts(location.origin + '/workers/xlsx.core.min.js')
//因为woker中是有loaction变量的,所以可以通过服务器的绝对路径进行访问,以获得XLSX。
const ws = XLSX.utils.aoa\_to\_sheet(data)
三、封装相应的table组件
**下面是我封装的组件,如果是使用elementUI可以直接引入,若没有使用可以把elementUi相关标签删除替换即可。**
vxe-table的Api文档:https://vxetable.cn/v3/#/table/api
组件传参说明:仅有两个参数
| rowList| 行记录数据 |
|--|--|
| colList | 列记录数据 |
<result-table :rowList="rowList" :colList="colList"> </result-table>
<template>
<div style="height: 100%">
<div style="display: flex; justify-content: flex-end">
<el-pagination
background
layout="sizes,prev, pager, next,total"
:page-sizes="[10, 50, 100, 500, 1000]"
:current-page="currentPageNum"
:page-size="currentPageSize"
:total="rowListTotal"
@current-change="currentChange"
@size-change="handleSizeChange"
>
</el-pagination>
<el-button
type="primary"
@click="handleLargeDataExport"
size="small"
icon="el-icon-download"
style="z-index: 99; margin-right: 10px"
>导出全部</el-button
>
</div>
<div style="height: calc(100% - 80px); padding: 5px 10px">
<vxe-table
border
ref="xTable1"
height="100%"
empty-text="暂无数据"
show-overflow="title"
style="overflow: visible"
show-header-overflow
:row-config="{ isHover: true }"
:tooltip-config="{ showAll: true }"
>
<vxe-column
v-for="item in colList"
:field="item.name"
:resizable="true"
min-width="120"
:title="item.name"
:key="item.name"
></vxe-column>
</vxe-table>
</div>
</div>
</template>
<script>
export default {
data() {
return {
currentList: [], //当前页数据
currentPageNum: 1, //当前页码
currentPageSize: 50, //当前页尺寸
rowListTotal: 0 //结果总条数
}
},
props: {
//行数据
rowList: {
type: Array,
default: []
},
// 列数据
colList: {
type: Array,
default: []
}
},
created() {},
watch: {
rowList: {
handler(newVal, oldVal) {
console.log('rowListHandle')
this.rowListTotal = newVal.length
this.currentList = newVal.slice(0, this.currentPageSize)
this.currentPageNum = 1
},
immediate: true
},
currentList: {
handler(newVal, oldVal) {
console.log('currentListHandle')
this.$refs.xTable1.loadData(newVal)
}
}
},
methods: {
//当前页尺寸改变
handleSizeChange(pageSize) {
this.currentPageSize = pageSize
this.currentList = this.rowList.slice(
(this.currentPageNum - 1) \* this.currentPageSize,
this.currentPageNum \* this.currentPageSize
)
},
// 当前页码改变
currentChange(pageNum) {
this.currentPageNum = pageNum
this.currentList = this.rowList.slice(
(this.currentPageNum - 1) \* this.currentPageSize,
this.currentPageNum \* this.currentPageSize
)
},
// 全部结果导出
handleLargeDataExport() {
let handleData = this.rowList
if (handleData.length == 0) {
return this.$message('暂无数据!')
}
this.$message('正在导出,请稍后...')
this.$worker
.run(
(handleData) => {
// console.time('handelExcel')
let data = handleData.map((item, index) => {
let tempArr = []
for (let itemKey in item) {
tempArr.push(item[itemKey])
}
return tempArr
})
let keyArr = []
for (let itemKey in handleData[0]) {
keyArr.push(itemKey)
}
data.unshift(keyArr)
importScripts(location.origin + '/workers/xlsx.core.min.js')
// importScripts('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.15.3/xlsx.core.min.js')
const ws = XLSX.utils.aoa\_to\_sheet(data)
const wb = XLSX.utils.book\_new()
XLSX.utils.book\_append\_sheet(wb, ws, 'data')
const buf = XLSX.write(wb, { type: 'array', bookType: 'xlsx' })
// console.timeEnd('handelExcel')
return buf
},
[handleData]
)
.then((res) => {
this.$message({
message: '已生成文件!',
type: 'success',
duration: 2000
})
const url = window.URL.createObjectURL(new Blob([res]))
const link = document.createElement('a')
link.href = url
link.download = `全部结果\_${new Date().getTime()}.xlsx`
link.click()
})
.catch((err) => {
console.log(err)
})
}
}
}
</script>