公司在后台管理系統開發中用到了 vue+element-ui 組合的框架,但隨着需求的越來越復雜,前端的工作難度也呈幾何倍數遞增,工作量隨之增大。這不,在項目中增加一個將列表數據導出為excel的需求就緊跟着來了。
不光將數據導出,還得支持單筆導出或多筆批量導出。
前端:前端招誰惹誰了?
產品:入了前端門,生是前端人,死是前端鬼!
前端:
產品:
為了生活,我們已經殫精竭慮;為了工作,我們已經竭盡全力!
有需求,哭着也得實現啊。於是上網搜了一通,果然讓我發現了解決之道:xlsx、file-saver和script-loader。
接下來就說說具體的實現方法:
上邊提到了三個插件:xlsx、file-saver和script-loader,對,你沒看錯,就是三個插件,實現一個功能,需要三個插件,沒辦法啊。就像你的銀行卡要用六位數的密碼來保護兩位數的余額一樣,你有什么辦法呢?誰讓你敗家呢?
一、 安裝三個依賴項
npm install -S file-saver
npm install -S xlsx
npm install -D script-loader
二、在項目中新建一個文件夾(一般在src下新建,文件名自取,在這里命名為excel),在文件夾中放入Blob.js 和 export2Excel.js (這兩個文件可在gitup上進行下載)
三、vue組件調用(由於項目中很多頁面都會用到,所以我就封裝成了公共的方法)
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
/*
* 導出excel
* @param { Array } params.excelHeader 導出excel的表頭
* @param { Array } params.excelFilterVal 導出數據所需的字段(multipleSelection或defaultList對象的屬性)
* @param { Array } params.multipleSelection 導出勾選的單筆或多筆數據
* @param { Array } params.defaultList 默認導出列表所有數據
* @param { Array } params.fileName 導出excel的文件名
*/
export function export2Excel(params){
let excelHeader = params.excelHeader || ['類型', '合同號', '賬戶名', '幣種', '金額']
let excelFilterVal = params.excelFilterVal || ['type', 'contractCode', 'accountName', 'currency', 'amount']
require.ensure([], () => {
let { export_json_to_excel } = require('@/excel/Export2Excel');
//默認為導出全部列表,也可以單筆導出或勾選多筆批量導出
let listArr = params.multipleSelection.length > 0 ? JSON.parse(JSON.stringify(params.multipleSelection)) : JSON.parse(JSON.stringify(params.defaultList));
let formatData = formatJson(excelFilterVal, listArr);
export_json_to_excel(excelHeader, formatData, params.fileName);
})
}
function formatJson(excelFilterVal, listArr) {
return listArr.map(v => {
switch(v.type){
case '01':
v.type = '小貸';
break;
case '02':
v.type = '租賃';
break;
case '03':
v.type = '電商';
break;
}
return excelFilterVal.map(j => v[j]);
})
}
說明:
1、以上代碼在文件路徑上用到了“@”符號,不懂的同學可自行查閱資料;
2、以上代碼用到了JSON.stringify
和JSON.parse
,主要是因為對象的引用的問題。我們都知道,在將一個對象賦值給另一個對象時,如果其中一個對象的某個屬性值被修改了也會影響到另一個對象的某個屬性值的改變,這是因為他們在內存中實際上是指向了同一個引用地址,所以我就先用JSON.stringify
將目標對象(這里是一個數組,數組也是Object對象,沒毛病)轉變成一個字符串,讓其在內存中開辟一個新的地址,這樣就切斷了引用對象的指針聯系,然后再用JSON.parse
將字符串轉變為一個數組,就解決了引用對象之間互相影響的問題。導出excel方法中調用的formatJson函數中的type字段映射的文字跟頁面中映射的文字稍微不同(formatJson函數修改的是listArr數組,而listArr數組是通過頁面展示的默認數組defaultList或用戶選擇的數據數組multipleSelection賦值得來的),就會出現一個對象對另一個對象的影響,因此不得不使用了JSON.stringify
和JSON.parse
。
3、關於multipleSelection,這個是用了element-ui中el-table的多選功能。正是這個功能才是能實現單筆導出或多筆批量導出的關鍵,當選擇了單筆或多筆時,multipleSelection存儲的就是你選擇的數據(詳見element-ui的表格組件API),然后判斷該數組是否為空,若為空,則默認導出列表的所有數據,若不為空,則導出選擇的列表數據:
let listArr = params.multipleSelection.length > 0 ? JSON.parse(JSON.stringify(params.multipleSelection)) : JSON.parse(JSON.stringify(params.defaultList));
4、網上還有其他解決方案,詳見vue2.0 + element UI 中 el-table 數據導出Excel等等,此類方案倒沒有本文的解決方案那么麻煩,但有一個問題就是無法自行選擇具體導出表格哪些列的數據,它是一股腦將表格的所有數據都導出了,包括對表格數據的一些按鈕操作如修改按鈕、刪除按鈕等,甚至將表格第一列的checkbox復選框也導出了,雖然插件xlsx 有一個參數display為true時可以將隱藏的行和單元格的數組不被解析(具體使用方法沒有用過,不甚了解),但如果將表格的行或單元格設置為隱藏,那我們還在頁面中展示數據干嘛?顯然,這種解決方案雖然簡單,但靈活度不夠,適用於比較簡單的只展示數據的表格的導出。
本文參考:
https://blog.csdn.net/xiaoshihoukediaole/article/details/81296327
https://www.jianshu.com/p/6edf74f65fc1