下載表格組件是根據我自己的業務需求來封裝的
使用的是vue中 xlsx 的插件,需要安裝新的依賴及配置
僅供參考 不保證和你百分百匹配
安裝依賴
npm install -S file-saver xlsx
npm install -D script-loader
下載所需js
鏈接: https://pan.baidu.com/s/170okRAPiWxQrBvlDEpp7SQ 提取碼: gsf5
百度網盤真特喵的是個好東西啊
因為我的子組件引用了該js 如果你不想自己再修改位置,可以跟我一樣,
在src中,建立excel文件,將下載的js扔進去
組件調用
直接說調用部分,文章最后會把組件的代碼貼出來
父組件引入子組件
import exportTable from '@/components/common/exportTable';
......
components:{
exportTable
}
父組件調用子組件
<export-table ref="childRefName" :export-prepare.sync="exportPrepare" :list-query.sync="listQuery"></export-table>
參數詳解
exportPrepare:{ percentage: 0, //導出數據完成的百分比 name:'消耗記錄',//導出表格名稱 pageType:'pagination',//導出數據獲取方式:offset為偏移量、pagination為分頁 默認值為pagination limit:200,//單頁數據數量 最大值為200 超過200 按200讀取(自定義)或 perPage: 200(根據接口參數決定使用limit/perPage,暫時僅支持limit/perPage) total:0,//導出數據總數 json_fields: { // excel 表頭(具體名稱根據實際情況而定) '耗材編號': 'String', '耗材品牌': 'String', '耗材類型': 'String', '耗材名稱': 'String', '規格型號': 'String', '耗材屬性': 'String', '耗材價格': 'Number', '消耗類型': 'String', '消耗地點': 'String', '出庫倉': 'String', '目標設備': 'String', '操作人': 'String', '操作時間': 'String' }, json_relationship:{ //導出數據對應的字段名稱(具體字段根據實際情況而定 key值與表頭保持一致) '耗材編號': 'supplies_number', '耗材品牌': 'brand_name', '耗材類型': 'type', '耗材名稱': 'supplies_name', '規格型號': 'spec_name', '耗材屬性': 'spec_attribute', '耗材價格': 'cost', '消耗類型': 'supplies_type', '消耗地點': 'out_address', '出庫倉': 'warehouse_name', '目標設備': 'device_id', '操作人': 'staff_name', '操作時間': 'updated_at' }, param:{},//獲取導引數據接口所需的參數 dataList:[] }
注:json_relationship的值一定與json_fields的值保持一致,否則導出的表會出現空表的問題
listQuery: { // 列表請求數據 where: {},//where是我的接口用到的篩選數據的條件 沒有可以直接去掉 page: 1, limit: 20 }
注:子組件導出數據時頁碼,會引起父頁面修改exportPrepare的param的page、limit參數,使用listQuery進行獨立數據深拷貝,子組件的參數變化就不會引起父頁面的變化
頁面處理導出數據
父組件內獲取導出數據的方法
getExcelData(){
this.$refs.exportExcel.index+=1;
if(this.$refs.exportExcel.index<this.$refs.exportExcel.params.length) {
suppliesWaitInExcelData( this.$refs.exportExcel.params[this.$refs.exportExcel.index]).then((response) => {
const data = this.data_ext ? response[this.data_ext].data : response.data;
//data的值,需要根據實際的response數據格式進行賦值
const relationship = this.exportPrepare.json_relationship;
for (let i in data) {
var item = {};
for (let attr in relationship) {
item[attr] = !data[i][relationship[attr]] && data[i][relationship[attr]] !== 0 ? '' : data[i][relationship[attr]];
}
this.exportPrepare.dataList.push(item);
}
this.exportPrepare.percentage = Number((this.exportPrepare.dataList.length / this.exportPrepare.total*100).toFixed(0)) || 0;
this.getExcelData();
})
.catch(e=>{//這里是處理接口獲取失敗的情況 => 重新執行該條 知道走通(不需要可以把這個部分清空)
console.log('失敗了')
this.$refs.exportExcel.index-=1;
this.getExcelData();
})
}
}
注:getExcelData:為固定方法名稱,不可以自定義(子組件內有調用 除非兩者保持一致)
suppliesWaitInExcelData:獲取導出數據的接口api名稱,根據具體項目需求更換(接口封裝方法不同,調用api方法不同,請根據實際情況修改)
子組件封裝
注:子組件中用到this.$parents.doSomeThing()的方式去尋找父組件的方法,所以子組件不能被包裹在別的組件中(包括ele、el-row等element或自定義組件),否則會因為父組件層級問題,找不到對應的父組件方法
或者根據具體情況修改子組件內的方法 ex:this.$parents.$parents.doSomeThing() 多找一層parent 有可能會找到 但是不推薦

<template> <div id="export-excel"> <el-button type="primary" icon="document" class="export-btn" @click="init">導出數據</el-button> <el-dialog title="導出" :visible.sync="form.dialogFormVisible" size="tiny" :before-close="handleClose"> <div class="prev-btn right"> <el-progress :percentage="exportPrepare.percentage" style="margin-bottom: 20px;"></el-progress> <p style="color:#F56C6C;font-size:12px;" v-show="exportTips">數據量過大,推薦選擇精確數據下載</p> <el-button type="primary" @click="exportAction" v-if="exportPrepare.total == exportPrepare.dataList.length">導出</el-button> <el-button type="primary" class="cancel-action" v-else>導出</el-button> <el-button @click="handleClose">取消</el-button> </div> </el-dialog> </div> </template> <script type="application/ecmascript"> export default { name: "export-excel", props: { exportPrepare: { type: Object }, listQuery: { type: Object } }, data() { return { params: [], paramsItem: {}, index: -1, // 導出表單所需數據對象 form: { loading: false, dialogFormVisible: false, }, pageType: 'pagination', //獲取數據方式 pagination為分頁方式 offset為偏移量方式 json_meta: [ // 設置字符集 [{ key: "charset", value: "utf-8" }] ], // excel表頭 json_data: [], // 要導出的數據 dataList: [], // 要導出的數據 button_text: '', // 導出按鈕名稱 data_ext: '', // 數據后綴 防止返回的數據格式不是[obj, obj...] childExportPrepare:{}, exportTips:false,//數據過大提示 }; }, mounted() { this.pageType = this.exportPrepare.pageType || 'pagination' this.childExportPrepare = JSON.parse(JSON.stringify(this.listQuery)) }, watch: { listQuery(newValue, oldValue) { this.childExportPrepare = JSON.parse(JSON.stringify(this.listQuery)) } }, methods: { // 導出初始化 init() { this.form.dialogFormVisible = true; this.data_ext = this.exportPrepare.data_ext || ''; this.fetchExportList(); }, // 數據列表分次獲取 fetchExportList() { this.childExportPrepare = JSON.parse(JSON.stringify(this.listQuery)) this.exportPrepare.dataList = []; this.index = -1; this.params = []; this.exportPrepare.percentage = 0; this.json_data = []; if (this.pageType == 'offset') { if(this.exportPrepare.limit){ if (this.exportPrepare.total > this.exportPrepare.limit) { this.json_data = []; let param = {} param = this.childExportPrepare for (let i = 0; i < Math.ceil(this.exportPrepare.total / this.exportPrepare.limit); i++) { if(i>=20){ this.exportTips = true; }else{ this.exportTips = false; } if(this.exportPrepare.limit>200){ this.exportPrepare.limit = 200; } var startPage = 0, endlimit = 0; startPage = i * this.exportPrepare.limit; this.$set(param,'page',startPage) endlimit = this.exportPrepare.limit; if (i >= Math.ceil(this.exportPrepare.total / this.exportPrepare.limit) - 1 && this.exportPrepare.total % this.exportPrepare.limit != 0) { endlimit = this.exportPrepare.total % this.exportPrepare.limit } this.$set(param,'limit',endlimit) let paramList = {page:param.page,limit:param.limit}; this.form.loading = true; this.params.push(Object.assign(paramList,this.childExportPrepare)); } this.$parent.$parent.getExcelData() this.json_data = this.exportPrepare.dataList; } else { this.json_data = []; this.params = []; this.childExportPrepare.page = 0; this.childExportPrepare.limit = this.exportPrepare.total; let param = []; param.page = 0; param.limit = this.exportPrepare.total; let paramList = {page:param.page,limit:param.limit}; this.params.push(Object.assign(paramList,this.childExportPrepare)); this.form.loading = true; this.$parent.$parent.getExcelData(); this.json_data = this.exportPrepare.dataList; } }else{ if (this.exportPrepare.total > this.exportPrepare.perPage) { this.json_data = []; let param = {}; param = this.childExportPrepare for (let i = 0; i < Math.ceil(this.exportPrepare.total / this.exportPrepare.perPage); i++) { if(i>=20){ this.exportTips = true; }else{ this.exportTips = false; } if(this.exportPrepare.perPage>200){ this.exportPrepare.perPage = 200; } var startPage = 0, endlimit = 0; startPage = i * this.exportPrepare.perPage; this.$set(param,'page',startPage) endlimit = this.exportPrepare.perPage; if (i >= Math.ceil(this.exportPrepare.total / this.exportPrepare.perPage) - 1 && this.exportPrepare.total % this.exportPrepare.perPage != 0) { endlimit = this.exportPrepare.total % this.exportPrepare.perPage } this.$set(param,'perPage',endlimit) let paramList = {page:param.page,perPage:param.perPage}; this.form.loading = true; this.params.push(Object.assign(paramList,this.childExportPrepare)); } this.$parent.$parent.getExcelData() this.json_data = this.exportPrepare.dataList; } else { this.json_data = []; this.params = []; this.childExportPrepare.page = 0; this.childExportPrepare.limit = this.exportPrepare.total; let param = []; param.page = 0; param.perPage = this.exportPrepare.total; let paramList = {page:param.page,perPage:param.perPage}; this.params.push(Object.assign(paramList,this.childExportPrepare)); this.form.loading = true; this.$parent.$parent.getExcelData(); this.json_data = this.exportPrepare.dataList; } } } else { if(this.exportPrepare){ if (this.exportPrepare.total > this.exportPrepare.limit) { this.json_data = []; let param = {} param = this.childExportPrepare for (let i = 0; i < Math.ceil(this.exportPrepare.total / this.exportPrepare.limit); i++) { if(i>=20){ this.exportTips = true; }else{ this.exportTips = false; } if(this.exportPrepare.limit>200){ this.exportPrepare.limit = 200; } let startPage = 0, endlimit = 0; startPage = i + 1; this.$set(param,'page',startPage) endlimit = this.exportPrepare.limit; if (i >= Math.ceil(this.exportPrepare.total / this.exportPrepare.limit) - 1 && this.exportPrepare.total % this.exportPrepare.limit != 0) { endlimit = this.exportPrepare.total % this.exportPrepare.limit } this.$set(param,'limit',endlimit) let paramList = {page:param.page,limit:param.limit}; this.form.loading = true; this.params.push(Object.assign(paramList,this.childExportPrepare)); } this.$parent.$parent.getExcelData() this.json_data = this.exportPrepare.dataList; } else { this.json_data = []; this.params = []; this.childExportPrepare.page = 1; this.childExportPrepare.limit = this.exportPrepare.total; let param = []; param.page = 1; param.limit = this.exportPrepare.total; let paramList = {page:param.page,limit:param.limit}; this.params.push(Object.assign(paramList,this.childExportPrepare)); this.form.loading = true; this.$parent.$parent.getExcelData(); this.json_data = this.exportPrepare.dataList; } }else{ if (this.exportPrepare.total > this.exportPrepare.perPage) { this.json_data = []; let param = {} param = this.childExportPrepare for (let i = 0; i < Math.ceil(this.exportPrepare.total / this.exportPrepare.perPage); i++) { if(i>=20){ this.exportTips = true; }else{ this.exportTips = false; } if(this.exportPrepare.perPage>200){ this.exportPrepare.perPage = 200; } var startPage = 0, endlimit = 0; startPage = i + 1; this.$set(param,'page',startPage) endlimit = this.exportPrepare.perPage; if (i >= Math.ceil(this.exportPrepare.total / this.exportPrepare.perPage) - 1 && this.exportPrepare.total % this.exportPrepare.perPage != 0) { endlimit = this.exportPrepare.total % this.exportPrepare.perPage } this.$set(param,'perPage',endlimit) let paramList = {page:param.page,perPage:param.perPage}; this.form.loading = true; this.params.push(Object.assign(paramList,this.childExportPrepare)); } this.$parent.$parent.getExcelData() this.json_data = this.exportPrepare.dataList; } else { this.json_data = []; this.params = []; this.childExportPrepare.page = 1; this.childExportPrepare.limit = this.exportPrepare.total; let param = []; param.page = 1; param.perPage = this.exportPrepare.total; let paramList = {page:param.page,perPage:param.perPage}; this.params.push(Object.assign(paramList,this.childExportPrepare)); this.form.loading = true; this.$parent.$parent.getExcelData(); this.json_data = this.exportPrepare.dataList; } } } }, //導出 exportAction() { if (this.exportPrepare.total == this.json_data.length) { require.ensure([], () => { const { export_json_to_excel } = require('../../excel/Export2Excel'); const tHeader = []; for (let i in this.exportPrepare.json_fields) { tHeader.push(i); } if (this.json_data.length < 1) { this.fetchExportList(); return } const list = this.json_data; const data = this.formatJson(tHeader, list); export_json_to_excel(tHeader, data, this.exportPrepare.name || '導出數據'); this.form.loading = true; setTimeout(() => { this.form.loading = false; this.$notify({ title: '成功', message: '導出成功', type: 'success', duration: 1500 }); this.form.dialogFormVisible = false; this.json_data = []; this.dataList = []; this.exportPrepare.dataList = []; }, 500); }) } }, formatJson(filterVal, jsonData) { return jsonData.map(v => filterVal.map(j => v[j])) }, // 關閉導出對話框 handleClose() { this.form.dialogFormVisible = false; this.exportPrepare.dataList = []; this.json_data = []; this.dataList = []; this.params = []; this.exportPrepare.percentage = 0; } } } </script> <style scoped="scoped" lang="scss"> .cancel-action { opacity: .4; } .right { text-align: right; } #export-excel{ float: right; } </style>