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

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、组件开发目的

  • 重写 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导出相关方法
    async exportToExcel() {
      // 1.创建工作簿
      await this.createWorkBook();
      // 2.创建工作表
      const promise = [];
      await this.book.sheets.forEach((sheet) => {
        promise.push(this.createWorkSheet(sheet.sheetName, sheet.sheetData));
      });
      await Promise.all(promise);
      // 3.下载excel表格
      await this.downloadExcel();
    },
    createWorkBook() {
      this.workbook = new ExcelJS.Workbook();
      this.workbook.created = new Date();
      this.workbook.modified = new Date();
      this.workbook.lastPrinted = new Date();
    },
    async 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官网教程,自行封装。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达娃里氏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值