最近业务上有数据大屏的需要,要求不仅能展现数据,同时能提供所选日期范畴的数据下载。本文纯记录实现计划作为笔记,实现细节非常不齐备。工具库xlsx电子表格的标准规范详见:Full XML Schema。上面两个库都基于这个标准实现了这类格式文件的读写(salute!∠(°ゝ°))。
SheetJSSheetJS是用于多种电子表格格局的解析器和编写器。通过官网标准、相干文档以及测试文件实现简洁的JS办法。SheetJS强调解析和编写的持重,其跨格局的特点和对立的JS标准兼容,并且ES3/ES5浏览器向后兼容IE6。
excelizeGo语言编写的能够读写电子表格类型文件的公共库
更静默:webworkerWeb Worker为Web内容在后盾线程中运行脚本提供了一种简略的办法。线程能够执行工作而不烦扰用户界面。咱们将SheetJS解决数据、生成表格数据(book类型数据)的流程另起一个线程实现。(尽管另起一个线程从体验上不会适度影响主UI线程,但自身启动老本比拟高)。
该组件的目录如下
NewDashboard├── components│ ├── LongCard│ │ ├── echartsOption.ts│ │ ├── index.tsx│ │ └── style.module.less│ └── ShortCard│ ├── echartsOption.ts│ ├── index.tsx│ └── style.module.less├── index.tsx # 在该文件与webworker通信├── makeTable.ts # 在该文件实现webworker└── style.module.lessmdn给的samples的worker都是加载内部代码的。在咱们这种组织目录下,worker应该在一个文件内实现,并导出一个worker实例。这里须要借助URL.createObjectURL(blob)结构一个外链。
代码如下:
// @file makeTable.tsconst blob = new Blob( [ ` importScripts('https://g.alicdn.com/code/lib/xlsx/0.17.4/xlsx.full.min.js'); const GOODS_EFFECT_TITLE = [ '开播工夫', '下播工夫', '直播间', '商品名称', '商品', '点击人数', '成交人数', '粉丝成交比例', '疏导成交金额', ]; // 接管主过程的表格数据 onmessage = function({ data }) { console.log('from main routine', data); const book = XLSX.utils.book_new(); const sheet = XLSX.utils.aoa_to_sheet([GOODS_EFFECT_TITLE, ...data]); XLSX.utils.book_append_sheet(book, sheet, '工作表1'); // book的数据回传给主过程 postMessage({ book }); };`, ], { type: 'text/javascript' },);export const worker = new Worker(URL.createObjectURL(blob));留神几个点:
因为在worker内没有DOM、windows等对象,所以没有方法间接应用 XLSX.utils.table_to_book 办法将table元素间接导出为xlsx表格数据。importScript 办法是并行加载所有列出的资源,但执行是同步的。这里须要将SheetJS的资源加载进worker里。主过程的办法: // @file index.tsximport { worker } from './makeTable';function download() { // aoa_to_sheet 办法须要一个二维数组来造成电子表格 worker.postMessage([[1, 2, 3]]); worker.onmessage = ({ data }) => { window.XLSX.writeFile(data.book, '测试.xlsx'); }; }更高速:WebAssembly对于网络平台而言,WebAssembly具备微小的意义——它提供了一条路径,以使得以各种语言编写的代码都能够以靠近原生的速度在Web中运行。在这种状况下,以前无奈以此形式运行的客户端软件都将能够运行在Web中。咱们应用Go语言编译为wasm文件,外围代码如下:
// wasm.gofunc main() { c := make(chan struct{}, 0) // js全局办法makeExcel js.Global().Set("makeExcel", js.FuncOf(jsMakeExcel)) // 确保Go程序不退出 <-c }func makeExcel() []uint8 { f := excelize.NewFile() f.SetCellValue("Sheet1", "开播工夫", now.Format(time.ANSIC)) f.SetCellValue("Sheet1", "直播间", 1111) // 在js环境中无奈实现文件的操作 // if err := f.SaveAs("simple.xlsx"); err != nil { // log.Fatal((err)) // } buf, _ := f.WriteToBuffer() res := make([]uint8, buf.Len()) buf.Read(res) return res}func jsMakeExcel(arg1 js.Value, arg2 []js.Value) interface{} { buf := makeExcel() js_uint := js.Global().Get("Uint8Array").New(len(buf)) js.CopyBytesToJS(js_uint, buf) //go的uint8无奈间接回传,须要创立js环境的Uint8Array类型数据并回传 return js_uint}将编译好的wasm文件加载进js环境
引入桥接代码:https://github.com/golang/go/...。此时window下会有一个全局构造函数:Go样板代码——实例化webassembly:// WebAssembly.instantiateStreaming is not currently available in Safari if (WebAssembly && !WebAssembly.instantiateStreaming) { // polyfill WebAssembly.instantiateStreaming = async (resp, importObject) => { const source = await (await resp).arrayBuffer(); return await WebAssembly.instantiate(source, importObject); }; } const go = new Go(); fetch('path/to/wasm.wasm') .then((response) => response.arrayBuffer()) .then((bytes) => WebAssembly.instantiate(bytes, go.importObject)) .then((res) => go.run(res.instance))实现文件下载function download() { // 与一般办法一样调用go写入全局的办法,拿到刚刚回传的uint8array数据 const buf = makeExcel(); // 创立下载链接,留神文件类型,并下载文件 const blob = new Blob([buf], { type: 'application/vnd.ms-excel', }); const url = URL.createObjectURL(blob); console.log({ blob, str }); const a = document.createElement('a'); a.download = 'test.xlsx'; a.href = url; a.click();}既要又要webworker和webassembly是能够一起应用的,待补充……