likes
comments
collection
share

还在为Vue导出Excel而头疼?试试我这个组件!

作者站长头像
站长
· 阅读数 57

一、组件开发目的

  • 重写 Elementel-button 组件,实现在点击按钮的同时,将需要导出的数据导出到Excel文件中。

二、组件开发依赖

  • exceljs^4.3.0
  • file-saver^2.0.5

三、组件代码

<!-- 该组件重写了el-button组件,支持el-button所有用法 -->
<!-- 1、增加了导出excel的功能:父组件通过传递book参数,将表格数据传递给本组件,由本组件负责导出为excel -->
<template>
  <button
    class="el-button"
    @click="handleClick"
    :disabled="buttonDisabled || loading"
    :autofocus="autofocus"
    :type="nativeType"
    :class="[
      type ? 'el-button--' + type : '',
      buttonSize ? 'el-button--' + buttonSize : '',
      {
        'is-disabled': buttonDisabled,
        'is-loading': loading,
        'is-plain': plain,
        'is-round': round,
        'is-circle': circle
      }
    ]"
  >
    <i class="el-icon-loading" v-if="loading"></i>
    <i :class="icon" v-if="icon && !loading"></i>
    <span v-if="$slots.default"><slot></slot></span>
  </button>
</template>
<script>
import resolveResponse from '@/util/response';
import ExcelJS from 'exceljs';
import FileSaver from 'file-saver';

export default {
  name: 'ExportToExcelButton',
  inject: {
    elForm: {
      default: '',
    },
    elFormItem: {
      default: '',
    },
  },
  props: {
    type: {
      type: String,
      default: 'default',
    },
    size: String,
    icon: {
      type: String,
      default: '',
    },
    nativeType: {
      type: String,
      default: 'button',
    },
    loading: Boolean,
    disabled: Boolean,
    plain: Boolean,
    autofocus: Boolean,
    round: Boolean,
    circle: Boolean,
    book: {
      type: Object,
      default() {
        return {
          fileName: '',
          sheets: [
            {
              sheetName: '',
              sheetData: [[], [], []],
            },
          ],
        };
      },
    },
  },
  computed: {
    // eslint-disable-next-line no-underscore-dangle
    _elFormItemSize() {
      return (this.elFormItem || {}).elFormItemSize;
    },
    buttonSize() {
      // eslint-disable-next-line no-underscore-dangle
      return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
    },
    buttonDisabled() {
      return this.disabled || (this.elForm || {}).disabled;
    },
  },
  data() {
    return {
      loadingFlag: false,
      workbook: {},
    };
  },
  methods: {
    // el-button原生方法
    handleClick(evt) {
      this.$emit('click', evt); // 将click事件传给父组件
      this.exportToExcel(); // 导出excel
    },
    // excel导出相关方法
    exportToExcel() {
      // 1.创建工作簿
      this.createWorkBook();
      // 2.创建工作表
      const promise = [];
      this.book.sheets.forEach((sheet) => {
        promise.push(this.createWorkSheet(sheet.sheetName, sheet.sheetData));
      });
      Promise.all(promise);
      // 3.下载excel表格
      this.downloadExcel();
    },
    createWorkBook() {
      this.workbook = new ExcelJS.Workbook();
      this.workbook.created = new Date();
      this.workbook.modified = new Date();
      this.workbook.lastPrinted = new Date();
    },
    createWorkSheet(sheetName, sheetData) {
      const workSheet = this.workbook.addWorksheet(sheetName);
      workSheet.addRows(sheetData);
    },
    downloadExcel() {
      this.workbook.xlsx.writeBuffer()
        .then((buffer) => {
          FileSaver.saveAs(new Blob([buffer]), `${this.book.fileName}_${Date.now()}.xlsx`);
        })
        .catch((err) => {
          this.$message.error(`excel导出失败,原因为:${err}`);
        });
    },
  },
};
</script>

四、组件使用方法

  • 在vue项目里导入exceljsfile-saver相关依赖。
  • 新建一个名为ExportToExcelButton的vue文件,把第三部分的代码复制进去。
  • 在父组件里注册ExportToExcelButton组件,并把需要导出的数据通过ExportToExcelButton组件的book参数传给ExportToExcelButton组件。
  • 由于是重写的el-buton组件,所以ExportToExcelButton组件支持el-button组件的所有方法,且不需要element-ui依赖。el-button组件的用法可以参考:官方文档
  • 使用Demo:
<template>
  <export-to-excel-button
    type="primary"
    :book="book"
  >
    Demo
  </export-to-excel-button>
</template>

<script>
import ExportToExcelButton from '@/components/button/ExportToExcelButton.vue';

export default {
  name: 'Demo',
  components: { ExportToExcelButton },
  data() {
    return {
      book: {
        fileName: 'Demo',
        sheets: [
          {
            sheetName: 'sheet1',
            sheetData: [
              ['A1'],
              ['A2', 'B2'],
              ['A3', 'B3', 'C3'],
            ],
          },
          {
            sheetName: 'sheet2',
            sheetData: [
              ['A1', 'B1', 'C1'],
              ['A2', 'B2'],
              ['A3'],
            ],
          },
        ],
      },
    };
  },
};
</script>

<style scoped>

</style>

五、不足之处

  • 目前组件还不支持富文本和图片,有兴趣的可以根据ExcelJS官网教程,自行封装。
转载自:https://juejin.cn/post/7085190593046904846
评论
请登录