最近业务有数据大屏需求,不仅需要展示数据,还需要提供选定日期范围的数据下载。本文纯粹以笔记的形式记录实现方案,实现细节非常不完整。有关工具库xlsx电子表格的标准规范,请参阅:FullXMLSchema。下面两个库就是基于这个规范实现了对这种格式文件的读写(敬礼!∠(°ゝ°))。SheetJSSheetJS是多种电子表格格式的解析器和编写器。通过官方规范、相关文档、测试文件实现简洁的JS方法。SheetJS强调解析和编写的健壮性,其跨格式特性兼容统一的JS规范,ES3/ES5浏览器向下兼容IE6。用excelizeGo语言编写的可以读写电子表格类型文件的公共库比较安静:webworkerWebWorker为网页内容提供了一种在后台线程中运行脚本的简便方法。线程可以在不干扰用户界面的情况下执行任务。我们将在另一个线程中实现SheetJS处理数据和生成表格数据(书本类数据)的过程。(虽然从体验上来说开启另一个线程不会对UI主线程造成太大的影响,但是本身的启动成本还是比较高的)。组件目录如下NewDashboard├──components│├──LongCard││├──echartsOption.ts││├──index.tsx││└──style.module.less│└──ShortCard│├──echartsOption.ts│├──index.tsx│└──style.module.less├──index.tsx#在这个文件中与webworker通信├──makeTable.ts├──lele└──implement该文件中的webworker.lessmdn给出的samples的worker都是加载外部代码的。在我们的组织目录中,worker应该在一个文件中实现并导出一个worker实例。这里需要使用URL.createObjectURL(blob)来构造外部链接。代码如下://@filemakeTable.tsconstblob=newBlob([`importScripts('https://g.alicdn.com/code/lib/xlsx/0.17.4/xlsx.full.min.js');constGOODS_EFFECT_TITLE=['开始时间','下载时间','直播间','产品名称','产品','点击数','交易数','粉丝交易比例','指南TransactionAmount',];//从主进程接收表数据onmessage=function({data}){console.log('frommainroutine',data);constbook=XLSX.utils.book_new();constsheet=XLSX.utils.aoa_to_sheet([GOODS_EFFECT_TITLE,...data]);XLSX.utils.book_append_sheet(book,sheet,'Worksheet1');//书的数据传回主进程postMessage({book});};`,],{type:'text/javascript'},);exportconstworker=newWorker(URL.createObjectURL(blob));注意几点:由于worker中没有DOM、windows等对象,所以没办法直接使用XLSX.utils.table_to_book方法直接将表格元素导出为xlsx表格数据。importScript方法是并行加载所有列出的资源,但执行是同步的。这里需要将SheetJS的资源加载到worker中。主进程的方法://@fileindex.tsximport{worker}from'./makeTable';functiondownload(){//aoa_to_sheet方法需要一个二维数组来组成电子表格worker.postMessage([[1,2,3]]);worker.onmessage=({data})=>{window.XLSX.writeFile(data.book,'test.xlsx');};意思是——它提供了一种方法,可以让用任何语言编写的代码以接近本机的速度在Web上运行。在这种情况下,以前无法以这种方式运行的客户端软件将可以在Web上运行。我们使用Go语言编译成wasm文件,核心代码如下://wasm.gofuncmain(){c:=make(chanstruct{},0)//js全局方法makeExceljs.Global()。Set("makeExcel",js.FuncOf(jsMakeExcel))//确保Go程序不退出<-c}funcmakeExcel()[]uint8{f:=excelize.NewFile()f.SetCellValue("Sheet1","开始时间",now.Format(time.ANSIC))f.SetCellValue("Sheet1","LiveRoom",1111)//js环境下无法实现文件操作//iferr:=f.SaveAs("simple.xlsx");err!=nil{//log.Fatal((err))//}buf,_:=f.WriteToBuffer()res:=make([]uint8,buf.Len())buf.Read(res)返回res}funcjsMakeExcel(arg1js.Value,arg2[]js.Value)接口{}{buf:=makeExcel()js_uint:=js.Global().Get("Uint8Array").New(len(buf))js.CopyBytesToJS(js_uint,buf)//go的uint8不能直接返回,需要在js环境中创建Uint8Array类型的数据并返回returnjs_uint}将编译好的wasm文件加载到js环境中,引入桥接代码:https://github.com/golang/go/...。这时候window下会有一个全局的构造函数:Goboilerplatecode-instantiatewebassembly://WebAssembly.instantiateStreamingisnotcurrentlyavailableinSafariif(WebAssembly&&!WebAssembly.instantiateStreaming){//polyfillWebAssembly.instantiateStreaming(=resp,importObject)=>{constsource=await(awaitresp).arrayBuffer();返回等待WebAssembly.instantiate(source,importObject);};}constgo=newGo();.wasm').then((response)=>response.arrayBuffer()).then((bytes)=>WebAssembly.instantiate(bytes,go.importObject)).then((res)=>go.run(res.instance))实现文件下载函数download(){//像普通方法一样调用go写入全局方法,获取刚刚返回的uint8array数据constbuf=makeExcel();//创建下载链接,注意文件类型,下载文件constblob=newBlob([buf],{type:'application/vnd.ms-excel',});consturl=URL.createObjectURL(blob);console.log({blob,str});consta=document.createElement('a');a.download='test.xlsx';a.href=网址;a.click();}webworker和webassembly可以一起使用,待补充...
