# 一。安装依赖:
| npm install -S file-saver | |
| npm install -S xlsx | |
| npm install -D script-loader | 
# 二。将 Blob.js 和 Export2Excel.js 放到 src 的 lib 文件夹中(代码块不能折叠很难受 - -)
Blob.js:
| /* eslint-disable */ | |
| /* Blob.js | |
| * A Blob implementation. | |
| * 2014-05-27 | |
| * | |
| * By Eli Grey, http://eligrey.com | |
| * By Devin Samarin, https://github.com/eboyjr | |
| * License: X11/MIT | |
| * See LICENSE.md | |
| */ | |
| /*global self, unescape */ | |
| /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, | |
| plusplus: true */ | |
| /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ | |
| (function (view) { | |
| "use strict"; | |
| view.URL = view.URL || view.webkitURL; | |
| if (view.Blob && view.URL) { | |
| try { | |
| new Blob; | |
| return; | |
| } catch (e) {} | |
|     } | |
|     // Internally we use a BlobBuilder implementation to base Blob off of | |
|     // in order to support older browsers that only have BlobBuilder | |
| var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) { | |
|             var | |
| get_class = function(object) { | |
| return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; | |
|                 } | |
| , FakeBlobBuilder = function BlobBuilder() { | |
| this.data = []; | |
|                 } | |
| , FakeBlob = function Blob(data, type, encoding) { | |
| this.data = data; | |
| this.size = data.length; | |
| this.type = type; | |
| this.encoding = encoding; | |
|                 } | |
| , FBB_proto = FakeBlobBuilder.prototype | |
| , FB_proto = FakeBlob.prototype | |
| , FileReaderSync = view.FileReaderSync | |
| , FileException = function(type) { | |
| this.code = this[this.name = type]; | |
|                 } | |
| , file_ex_codes = ( | |
|                     "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " | |
| + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" | |
| ).split(" ") | |
| , file_ex_code = file_ex_codes.length | |
| , real_URL = view.URL || view.webkitURL || view | |
| , real_create_object_URL = real_URL.createObjectURL | |
| , real_revoke_object_URL = real_URL.revokeObjectURL | |
| , URL = real_URL | |
| , btoa = view.btoa | |
| , atob = view.atob | |
| , ArrayBuffer = view.ArrayBuffer | |
| , Uint8Array = view.Uint8Array | |
|                 ; | |
| FakeBlob.fake = FB_proto.fake = true; | |
| while (file_ex_code--) { | |
| FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; | |
|             } | |
| if (!real_URL.createObjectURL) { | |
| URL = view.URL = {}; | |
|             } | |
| URL.createObjectURL = function(blob) { | |
|                 var | |
| type = blob.type | |
|                     , data_URI_header | |
|                     ; | |
| if (type === null) { | |
| type = "application/octet-stream"; | |
|                 } | |
| if (blob instanceof FakeBlob) { | |
| data_URI_header = "data:" + type; | |
| if (blob.encoding === "base64") { | |
| return data_URI_header + ";base64," + blob.data; | |
| } else if (blob.encoding === "URI") { | |
| return data_URI_header + "," + decodeURIComponent(blob.data); | |
| } if (btoa) { | |
| return data_URI_header + ";base64," + btoa(blob.data); | |
| } else { | |
| return data_URI_header + "," + encodeURIComponent(blob.data); | |
|                     } | |
| } else if (real_create_object_URL) { | |
| return real_create_object_URL.call(real_URL, blob); | |
|                 } | |
| }; | |
| URL.revokeObjectURL = function(object_URL) { | |
| if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { | |
| real_revoke_object_URL.call(real_URL, object_URL); | |
|                 } | |
| }; | |
| FBB_proto.append = function(data/*, endings*/) { | |
| var bb = this.data; | |
|                 // decode data to a binary string | |
| if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { | |
|                     var | |
| str = "" | |
| , buf = new Uint8Array(data) | |
| , i = 0 | |
| , buf_len = buf.length | |
|                         ; | |
| for (; i < buf_len; i++) { | |
| str += String.fromCharCode(buf[i]); | |
|                     } | |
| bb.push(str); | |
| } else if (get_class(data) === "Blob" || get_class(data) === "File") { | |
| if (FileReaderSync) { | |
| var fr = new FileReaderSync; | |
| bb.push(fr.readAsBinaryString(data)); | |
| } else { | |
|                         // async FileReader won't work as BlobBuilder is sync | |
| throw new FileException("NOT_READABLE_ERR"); | |
|                     } | |
| } else if (data instanceof FakeBlob) { | |
| if (data.encoding === "base64" && atob) { | |
| bb.push(atob(data.data)); | |
| } else if (data.encoding === "URI") { | |
| bb.push(decodeURIComponent(data.data)); | |
| } else if (data.encoding === "raw") { | |
| bb.push(data.data); | |
|                     } | |
| } else { | |
| if (typeof data !== "string") { | |
| data += ""; // convert unsupported types to strings | |
|                     } | |
|                     // decode UTF-16 to binary string | |
| bb.push(unescape(encodeURIComponent(data))); | |
|                 } | |
| }; | |
| FBB_proto.getBlob = function(type) { | |
| if (!arguments.length) { | |
| type = null; | |
|                 } | |
| return new FakeBlob(this.data.join(""), type, "raw"); | |
| }; | |
| FBB_proto.toString = function() { | |
| return "[object BlobBuilder]"; | |
| }; | |
| FB_proto.slice = function(start, end, type) { | |
| var args = arguments.length; | |
| if (args < 3) { | |
| type = null; | |
|                 } | |
| return new FakeBlob( | |
| this.data.slice(start, args > 1 ? end : this.data.length) | |
|                     , type | |
| , this.encoding | |
| ); | |
| }; | |
| FB_proto.toString = function() { | |
| return "[object Blob]"; | |
| }; | |
| FB_proto.close = function() { | |
| this.size = this.data.length = 0; | |
| }; | |
| return FakeBlobBuilder; | |
| }(view)); | |
| view.Blob = function Blob(blobParts, options) { | |
| var type = options ? (options.type || "") : ""; | |
| var builder = new BlobBuilder(); | |
| if (blobParts) { | |
| for (var i = 0, len = blobParts.length; i < len; i++) { | |
| builder.append(blobParts[i]); | |
|             } | |
|         } | |
| return builder.getBlob(type); | |
| }; | |
| }(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); | 
Export2Excel.js:
| /* eslint-disable */ | |
| require('script-loader!file-saver'); | |
| require('script-loader!./Blob'); // 引用当前目录下的 Blob.js 模块 | |
| require('script-loader!xlsx/dist/xlsx.core.min'); | |
| // 由于这几个文件不支持 import 引入,所以我们需要 `script-loader` 来将他们挂载到全局环境下 | |
| function generateArray(table) { | |
| var out = []; | |
| var rows = table.querySelectorAll('tr'); | |
| var ranges = []; | |
| for (var R = 0; R < rows.length; ++R) { | |
| var outRow = []; | |
| var row = rows[R]; | |
| var columns = row.querySelectorAll('td'); | |
| for (var C = 0; C < columns.length; ++C) { | |
| var cell = columns[C]; | |
| var colspan = cell.getAttribute('colspan'); | |
| var rowspan = cell.getAttribute('rowspan'); | |
| var cellValue = cell.innerText; | |
| if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue; | |
|             //Skip ranges | |
| ranges.forEach(function (range) { | |
| if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) { | |
| for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null); | |
|                 } | |
| }); | |
|             //Handle Row Span | |
| if (rowspan || colspan) { | |
| rowspan = rowspan || 1; | |
| colspan = colspan || 1; | |
| ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}}); | |
|             } | |
|             ; | |
|             //Handle Value | |
| outRow.push(cellValue !== "" ? cellValue : null); | |
|             //Handle Colspan | |
| if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null); | |
|         } | |
| out.push(outRow); | |
|     } | |
| return [out, ranges]; | |
| }; | |
| function datenum(v, date1904) { | |
| if (date1904) v += 1462; | |
| var epoch = Date.parse(v); | |
| return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); | |
| } | |
| function sheet_from_array_of_arrays(data, opts) { | |
| var ws = {}; | |
| var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}}; | |
| for (var R = 0; R != data.length; ++R) { | |
| for (var C = 0; C != data[R].length; ++C) { | |
| if (range.s.r > R) range.s.r = R; | |
| if (range.s.c > C) range.s.c = C; | |
| if (range.e.r < R) range.e.r = R; | |
| if (range.e.c < C) range.e.c = C; | |
| var cell = {v: data[R][C]}; | |
| if (cell.v == null) continue; | |
| var cell_ref = XLSX.utils.encode_cell({c: C, r: R}); | |
| if (typeof cell.v === 'number') cell.t = 'n'; | |
| else if (typeof cell.v === 'boolean') cell.t = 'b'; | |
| else if (cell.v instanceof Date) { | |
| cell.t = 'n'; | |
| cell.z = XLSX.SSF._table[14]; | |
| cell.v = datenum(cell.v); | |
|             } | |
| else cell.t = 's'; | |
| ws[cell_ref] = cell; | |
|         } | |
|     } | |
| if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range); | |
| return ws; | |
| } | |
| function Workbook() { | |
| if (!(this instanceof Workbook)) return new Workbook(); | |
| this.SheetNames = []; | |
| this.Sheets = {}; | |
| } | |
| function s2ab(s) { | |
| var buf = new ArrayBuffer(s.length); | |
| var view = new Uint8Array(buf); | |
| for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; | |
| return buf; | |
| } | |
| export function export_table_to_excel(id) { | |
| var theTable = document.getElementById(id); | |
| console.log('a') | |
| var oo = generateArray(theTable); | |
| var ranges = oo[1]; | |
|     /* original data */ | |
| var data = oo[0]; | |
| var ws_name = "SheetJS"; | |
| console.log(data); | |
| var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); | |
|     /* add ranges to worksheet */ | |
|     // ws['!cols'] = ['apple', 'banan']; | |
| ws['!merges'] = ranges; | |
|     /* add worksheet to workbook */ | |
| wb.SheetNames.push(ws_name); | |
| wb.Sheets[ws_name] = ws; | |
| var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); | |
| saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx") | |
| } | |
| function formatJson(jsonData) { | |
| console.log(jsonData) | |
| } | |
| export function export_json_to_excel(th, jsonData, defaultTitle) { | |
|     /* original data */ | |
| var data = jsonData; | |
| data.unshift(th); | |
| var ws_name = "SheetJS"; | |
| var wb = new Workbook(), ws = sheet_from_array_of_arrays(data); | |
|     /* add worksheet to workbook */ | |
| wb.SheetNames.push(ws_name); | |
| wb.Sheets[ws_name] = ws; | |
| var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'}); | |
| var title = defaultTitle || '列表' | |
| saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx") | |
| } | 
# 三。在相应 vue 页面的 methods 中添加以下方法
| export2Excel(){ | |
| require.ensure([],()=>{ | |
| const {export_json_to_excel } = require('./../../lib/Export2Excel.js') | |
| const tHeader = ['组名','创建时间'] // 自定义列名 | |
| const filterVal = ['title','create_date'] // 对应自怼 | |
| const list = this.tableData //table 数据 | |
| const data = this.formatJson(filterVal,list); | |
| export_json_to_excel(tHeader,data,'列表excel'); // 导出文件名称 | |
| }) | |
| }, | |
| formatJson(filterVal,jsonData){ | |
| console.info(jsonData) | |
| return jsonData.map(v => filterVal.map(j=> v[j])) | |
| }, | |
| port(){ | |
| this.export2Excel() | |
| }, | 
# 四。绑定到 button 按钮
| <el-button size="small" type="success" @click="port">导出为excel表格</el-button> | 
