AdminJS创作之路

lxf2023-04-05 13:27:01

文中已参加「新手写作礼」主题活动,一起打开AdminJS创作之路。

一、组件开发目地

  • 重新写过 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官方网站实例教程,自主封装形式。