vue+xlsx實(shí)現(xiàn)表格導(dǎo)出進(jìn)度提示功能
引言
在處理大數(shù)據(jù)量(10萬+條)表格導(dǎo)出時(shí),常面臨以下問題:
- 瀏覽器卡頓無響應(yīng)
- 導(dǎo)出進(jìn)度不可見
- 導(dǎo)出失敗無反饋
本文將深度擴(kuò)展以下功能:
- 分片數(shù)據(jù)加載機(jī)制
- 實(shí)時(shí)進(jìn)度可視化
- 異常中斷處理
- 性能優(yōu)化策略
通過Ant Design Vue的Progress組件與自定義Hook,打造企業(yè)級(jí)導(dǎo)出體驗(yàn)。
一、進(jìn)度提示核心原理
1.1 分片加載模型
數(shù)據(jù)總量 → 分片大小 → 當(dāng)前分片 → 進(jìn)度百分比
↑ ↑ ↑
100,000條 5,000條/片 20次迭代
1.2 異步處理流程

二、完整實(shí)現(xiàn)方案
2.1 進(jìn)度條組件集成
<template>
<a-modal v-model:open="exportVisible" :footer="null">
<a-progress :percent="progress" status="active" />
<div style="margin-top: 16px">
{{ progress }}% 完成 | 當(dāng)前處理:{{ currentChunk }} / {{ totalChunks }} 分片
</div>
</a-modal>
</template>
<script setup>
import { ref } from 'vue'
const exportVisible = ref(false)
const progress = ref(0)
const currentChunk = ref(0)
const totalChunks = ref(0)
</script>
2.2 核心導(dǎo)出Hook(useExportProgress)
import { ref } from 'vue'
import * as XLSX from 'xlsx/xlsx.mjs'
import { saveAs } from 'file-saver'
export const useExportProgress = () => {
const isExporting = ref(false)
const progress = ref(0)
let workbook = null
let worksheet = null
const initWorkbook = () => {
workbook = XLSX.utils.book_new()
worksheet = XLSX.utils.aoa_to_sheet([])
XLSX.utils.book_append_sheet(workbook, worksheet, '大數(shù)據(jù)報(bào)表')
}
const exportData = async (config) => {
return new Promise(async (resolve, reject) => {
try {
isExporting.value = true
initWorkbook()
const { chunkSize, total, fetchData } = config
const totalChunks = Math.ceil(total / chunkSize)
for (let i = 0; i < totalChunks; i++) {
const data = await fetchData(i, chunkSize)
appendData(data)
updateProgress(i, totalChunks)
}
const blob = generateFile()
saveAs(blob, '大數(shù)據(jù)報(bào)表.xlsx')
resolve()
} catch (error) {
reject(error)
} finally {
isExporting.value = false
resetState()
}
})
}
const appendData = (data) => {
const startRow = worksheet['!ref']
? worksheet['!ref'].split(':')[1].replace(/[^0-9]/g, '') + 1
: 1
XLSX.utils.sheet_add_json(worksheet, data, {
origin: startRow,
skipHeader: true
})
}
const updateProgress = (current, total) => {
progress.value = Math.round((current / total) * 100)
}
const generateFile = () => {
return new Blob([XLSX.write(workbook, {
bookType: 'xlsx',
type: 'array'
})], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
})
}
const resetState = () => {
workbook = null
worksheet = null
progress.value = 0
}
return {
isExporting,
progress,
exportData
}
}
2.3 調(diào)用示例
<script setup>
import { useExportProgress } from './hooks/useExportProgress'
const { isExporting, progress, exportData } = useExportProgress()
// 模擬分片數(shù)據(jù)獲取
const fetchDataChunk = async (page, pageSize) => {
const start = page * pageSize
const end = start + pageSize
return new Promise(resolve => {
setTimeout(() => {
const mockData = Array.from({ length: pageSize }, (_, i) => ({
id: start + i + 1,
value: Math.random().toFixed(4)
}))
resolve(mockData)
}, 50)
})
}
const handleExport = async () => {
try {
await exportData({
chunkSize: 5000,
total: 100000,
fetchData: fetchDataChunk
})
} catch (error) {
console.error('導(dǎo)出失敗:', error)
}
}
</script>
三、性能優(yōu)化策略
3.1 內(nèi)存管理優(yōu)化
// 修改appendData方法
const appendData = (data) => {
// 每次處理后釋放內(nèi)存
const tempData = [...data]
XLSX.utils.sheet_add_json(worksheet, tempData, {
origin: -1,
skipHeader: true
})
tempData.length = 0 // 手動(dòng)GC
}
3.2 Web Worker方案
// worker.js
self.onmessage = async (e) => {
const { config, chunkIndex } = e.data
const data = await config.fetchData(chunkIndex, config.chunkSize)
self.postMessage({ chunkIndex, data })
}
// 主線程調(diào)用
const worker = new Worker('./worker.js')
worker.postMessage({ config, chunkIndex: i })
3.3 虛擬滾動(dòng)優(yōu)化
// 分片加載時(shí)動(dòng)態(tài)創(chuàng)建Worksheet
if (i === 0) {
XLSX.utils.book_append_sheet(workbook, worksheet, '數(shù)據(jù)分片1')
} else {
const newSheet = XLSX.utils.aoa_to_sheet([])
XLSX.utils.book_append_sheet(workbook, newSheet, `數(shù)據(jù)分片${i+1}`)
}
四、異常處理方案
4.1 斷點(diǎn)續(xù)傳實(shí)現(xiàn)
// 添加本地存儲(chǔ)
const saveProgress = (current) => {
localStorage.setItem('exportProgress', JSON.stringify({
currentChunk: current,
timestamp: Date.now()
}))
}
???????// 啟動(dòng)時(shí)檢查
const checkResume = () => {
const saved = localStorage.getItem('exportProgress')
if (saved && Date.now() - saved.timestamp < 300000) {
return JSON.parse(saved).currentChunk
}
return 0
}4.2 錯(cuò)誤邊界處理
<template>
<ErrorBoundary @error="handleError">
<YourExportComponent />
</ErrorBoundary>
</template>
<script setup>
const handleError = (error) => {
console.error('捕獲到導(dǎo)出錯(cuò)誤:', error)
// 發(fā)送錯(cuò)誤日志到服務(wù)端
}
</script>
五、生產(chǎn)級(jí)增強(qiáng)建議
導(dǎo)出日志記錄:記錄每次導(dǎo)出的關(guān)鍵指標(biāo)(耗時(shí)、數(shù)據(jù)量、異常)
權(quán)限校驗(yàn):在exportData方法前添加Token驗(yàn)證
格式預(yù)設(shè):預(yù)先定義單元格樣式模板
多格式支持:擴(kuò)展CSV/PDF導(dǎo)出選項(xiàng)
總結(jié)
通過本文實(shí)現(xiàn)的進(jìn)度提示方案,可獲得以下提升:
- 用戶體驗(yàn):實(shí)時(shí)反饋增強(qiáng)操作信心
- 系統(tǒng)穩(wěn)定性:分片加載降低內(nèi)存壓力
- 可維護(hù)性:Hook封裝提高代碼復(fù)用
- 錯(cuò)誤可追溯:完善的異常處理機(jī)制
到此這篇關(guān)于vue+xlsx實(shí)現(xiàn)表格導(dǎo)出進(jìn)度提示功能的文章就介紹到這了,更多相關(guān)vue表格導(dǎo)出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue中使用console.log打印的實(shí)現(xiàn)
這篇文章主要介紹了vue中使用console.log打印的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue登錄路由權(quán)限管理的項(xiàng)目實(shí)踐
使用electron-builder將項(xiàng)目打包成桌面程序的詳細(xì)教程
vue 自定義提示框(Toast)組件的實(shí)現(xiàn)代碼
Vue中如何實(shí)現(xiàn)在線預(yù)覽word文件、excel文件

