前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端万级数据量表格预览及前端导出Excel方案、组件封装(基于vxetable虚拟滚动和web worker)

前端万级数据量表格预览及前端导出Excel方案、组件封装(基于vxetable虚拟滚动和web worker)

原创
作者头像
用户10100319
发布2023-03-09 10:13:25
1.5K0
发布2023-03-09 10:13:25
举报
文章被收录于专栏:小硕前端开发

如题,本文主要解决前端展示渲染大数据量table数据及导出Excel的问题,主要是通过使用v3版本的vxetable和webworker来实现的。亲测可以表格可渲染30w条数据,可在10s内导出30w条数据Excel。

框架:vue2;

在这里插入图片描述
在这里插入图片描述
一、安装vxetable

可参考官网:https://vxetable.cn/v3/#/table/start/use

  1. 安装按需加载的插件
代码语言:shell
复制
npm install babel-plugin-import -D
  1. 修改文件 .babelrc 或 babel.config.js
代码语言:javascript
复制
{

        "plugins": [

          [

            "import",

            {

              "libraryName": "vxe-table",

              "style": true // 样式是否也按需加载

            }

          ]

        ]

      }
在这里插入图片描述
在这里插入图片描述
  1. main.js中全局按需引入模块
代码语言:javascript
复制
import { VXETable, Icon, Column, Table } from 'vxe-table'

Vue.use(Icon).use(Column).use(Table).use(VXETable)

**这样VXETable就已经在项目中安装注册完成,接下来进行安装vue-worker**

二、安装vue-worker
  1. 首先安装vue-worker插件;
代码语言:text
复制
npm install vue-worker -S
  1. 在main.js中引入
代码语言:javascript
复制
import VueWorker from 'vue-worker'

Vue.use(VueWorker)
  1. 引入导出XLSX的包

==这里有两种方式==

第一种方式:在web worker中使用XLSX的外部CDN链接

代码语言:javascript
复制
importScripts('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.15.3/xlsx.core.min.js')

然后就可以在web worker中全局使用XLSX了

第二张方式:将上面👆包的js链接下载到本地,放到项目的public文件夹下,可以再建一个workers文件夹存放,如下

在这里插入图片描述
在这里插入图片描述

然后再web worker中使用

代码语言:javascript
复制
//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 | 列记录数据 |

代码语言:javascript
复制
<result-table :rowList="rowList" :colList="colList"> </result-table>
代码语言:javascript
复制
<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>

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如题,本文主要解决前端展示渲染大数据量table数据及导出Excel的问题,主要是通过使用v3版本的vxetable和webworker来实现的。亲测可以表格可渲染30w条数据,可在10s内导出30w条数据Excel。
    • 一、安装vxetable
      • 二、安装vue-worker
        • 三、封装相应的table组件
        相关产品与服务
        内容分发网络 CDN
        内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档