zoukankan      html  css  js  c++  java
  • 封装Vue Element的upload上传组件

     

    本来昨天就想分享封装的这个upload组件,结果刚写了两句话,就被边上的同事给偷窥上了

    一直都很忙,写分享基本都是在中午午休时赶出来的,然后趁着在工作中颈椎疼的难以忍受时稍微休息一下的过程中排版发出来的。不过我也发现一个现象,就是我分享的有关封装的react方面的组件的关注度没有封装的vue方面的组件的关注度来得高,有可能是百度对我分享的vue方面的组件做了收录,所以大家也能在百度上搜索到,而我分享的react方面的组件却基本没有被百度收录的原因,或许也有可能是用vue的人多过用react的人,但我无意去对比两者,大家开心就好。

    今天写的这个upload组件也是采用的函数式组件,然后结合着Element ui的上传组件来封装,接下来就看具体实现吧。

    还是先来一张效果图:

    1、封装的上传组件Upload.js

    import { Message } from 'element-ui'
    const OSS = require("ali-oss");
    
    const SUFFIX = /.+(.w+)$/,
      TIMEOUT = 60000,
      BYTE = 1024,
      RETRY_COUNT_MAX = 3,
      ACCEPT = {
        zip: 'application/zip,application/x-zip,application/x-zip-compressed',
        pdf: 'application/pdf',
        excel: 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        image: 'image/jpeg,image/bmp,image/png,image/gif',
      },
      getAccepts = accept => (Array.isArray(accept) ? accept : [accept]).map(ac => ACCEPT[ac]).join(','),
      beforeCheck = (config, file) => {
        let {max = Number.MAX_VALUE, accept = []} = config || {}, { size, type } = file, accepts = getAccepts(accept).split(',');
        
        //大小限制(M)
        if(Math.pow(BYTE, 2) * max < size){
            Message.warning(`文件不能超过${max}M`);
            return false;
        }
      };
    
    export default {
      functional: true,
      props: {config: Object, limit: Number, percentage: Function},
      render: (h, ctx) => {
        let {props, data: attrs, parent: {$store: { dispatch}}, children} = ctx, { config, limit } = props, retryCount = 0, { accept } = config;
        if(!attrs.attrs.accept && accept){
          attrs.attrs.accept = getAccepts(accept);
        }
    
        Object.assign(props, {
          action: '',
          beforeUpload: file => beforeCheck(config, file),
          onExceed: () => Message.warning(`最多可以上传${limit}个文件`),
          httpRequest: opts => {
            let { file, onError, onProgress, onSuccess } = opts, { uid, name, type } = file;
            name = `${uid}${name.replace(SUFFIX, '$1')}`;
            if(getAccepts(accept).indexOf(type) > -1) file.isImg = true
    
            dispatch('getClient').then(res => {
              let aliClient = new OSS(res), { path } = res, url = path + '/' + name;
              //multipartUpload是阿里云的分片(分段)大文件上传方法,这里也可以用put方法来上传单个小文件(aliClient.put)
              aliClient.multipartUpload(url, file, {
                timeout: TIMEOUT,
                partSize: 500 * BYTE,
                progress: p => {
                  onProgress(p * 100, file)
                }
              }).then(r => {
                let { res: { requestUrls } } = r;
                requestUrls = requestUrls.length < 1 ? '' : requestUrls[0]
                if (requestUrls.indexOf('?') > -1) requestUrls = requestUrls.split('?')[0]
                onSuccess({ res: file, url: requestUrls });
              }).catch(err => {
                let { name } = err;
                if (aliClient.isCancel()) {
                  console.log('stop-upload!');
                } else {
                  Message.error(err);
                  onError(err);
                  if (name.toLowerCase().indexOf('connectiontimeout') !== -1) {
                    if (retryCount < RETRY_COUNT_MAX) {
                      retryCount++;
                      props.httpRequest(opt)
                    }
                  }
                }
              });;
            })
          }
        })
        return h('el-upload', {props, ...attrs}, children)
      }
    }
    

    本次封装的upload上传组件的封装方式和实现的功能与之前我所分享的封装React AntD的upload上传组件类似,你可以移步到那篇文章去详细了解,这里不再赘述。

    另外,我们公司所上传的文件都是上传到了阿里云,所以这里顺带着将上传到阿里云的方法也给粗略地实现了。上传到阿里云所用到的API请自行查阅,本次分享也不再赘述。

    2、使用方法:

    <template>
      <div class="container">
        <p>第一种上传形式:</p>
        <Upload :limit="limit" :on-success="onSuccess" :config="config" :on-progress="onProgress" :on-preview="onPreview" :on-remove="onRemove" list-type="picture-card">
          <i class="el-icon-plus"></i>
        </Upload>
        <br />
        <p>第二种上传形式:</p>
        <Upload :limit="limit" :on-success="onSuccess" :config="config" :on-progress="onProgress" :on-preview="onPreview" :on-remove="onRemove">
          <el-button size="small" type="primary">点击上传</el-button>
        </Upload>
      </div>
    </template>
    
    <script>
    import Upload from '@/components/Upload'
    
    export default {
      components: {
        Upload,
      },
      data() {
        return {
          limit: 1,
          config: {
            accept: "image", //接受上传的文件类型:zip、pdf、excel、image,也可以是文件类型所组成的数组类型如:['image', 'pdf'],则只可以上传图片或pdf类型的文件,也可以为空,则任何类型的文件都可以上传
            max: 100, //文件大小
          },
          fileList: [],
        }
      },
      methods: {
        //文件上传完成后的回调
        onSuccess({res: {uid, isImg}, url}) {
          this.fileList.push({uid, url})
        },
        //文件上传进度条
        onProgress(percent, file){
    
        },
        //上传文件
        onRemove(file){
          this.fileList = this.fileList.filter(n => n.uid != file.uid)
        },
      },
    }
    </script>
    

    以前去面试的时候,经常会有面试官问我在开发的过程中有没有自己封装过组件,我说封装过,然后面试官就让我举例,那时候我的回答一般都不是基于函数式的封装,都还是带有状态和生命周期函数的那种封装,但面试官也没说啥。后来接触到函数式组件,才觉得这玩意儿是真好使。

    PS:刚才发现我边上那个同事在用挖耳勺掏耳朵的时候还在偷瞄的电脑屏幕,册那!

  • 相关阅读:
    jquery 读取file 图片文件的宽高
    log4net配置要点
    js 公用插件,教科书级的写法
    mvc4 发布,遇到 403.14 问题,并且iis提示打开目录浏览。。。解决办法
    js 处理 html 标签转义 处理json中含有的ascii 编码
    sqlserver ,left join 不仅可以join表,还可以是一个结果集
    .net MVC3 页面和 action 传值问题
    java web工程 数据库操作报驱动类找不到的错误
    MySQL快速构造百万数据
    python之eval函数的应用实例
  • 原文地址:https://www.cnblogs.com/onesea/p/13609321.html
Copyright © 2011-2022 走看看