• vue-upload 封装组件-上传组件


    我后端的,刚接触vue个星期,根据需求写了个上传控件,很灵活的。没有看element el-upload源码,样式用的element的。感觉vue确实好用。

    先看样子:

    <!-- 单文件上传组件 -->
    <template>
    <div>
      <input type="file" id="file" hidden @change="fileChange" :accept="accept">
      <div v-if="upMode=='url'" style=" 100%;display:inline-flex;">    
        <el-input :value="path" disabled></el-input>
        <el-button size="small" type="primary" @click="btnChange">{{autoUpload?label:'选择文件'}}</el-button>
        <el-button v-if="!autoUpload && loadButton" size="small" type="success" @click="uploadClick">{{label}}</el-button>    
      </div>
      <div v-else-if="upMode=='head'" class="upmode-head">
        <div class="el-upload el-upload--picture-card" @click="btnChange">
          <i v-if="path==''" class="el-icon-plus"></i>
          <img v-else :src="path">
        </div>
        <el-button v-if="!autoUpload && loadButton" size="small" type="success" @click="uploadClick">{{label}}</el-button>
      </div>
      <div v-else-if="upMode=='variable'" class="el-upload-dragger" @click="btnChange">
        <div v-if="path==''">
          <i class="el-icon-upload"></i><div class="el-upload__text"><em>{{label}}</em></div>
        </div>
        <img v-else :src="path">
      </div>   
    
    </div>    
    </template>
    
    <script>
      import glob from '@/utils/global.js'
      export default {
        model: {   
          prop: 'path',
          event: 'onsuccess'
        },
        props: {
          label: {type: String, default: '上传'},//按钮文字
          accept: {String,default:'image/jpeg,image/png,image/x-icon'},//预选文件类型
          autoUpload:{type:Boolean, default:true},//是否自动上传
          loadButton:{type:Boolean, default:true},//手动上传时是否生成上传按钮
          path:String,//回显地址
          action: {type: String, default: '/api/upload/img'},//传入action可以调用不同接口适应不同文件类型上传
          upMode:{type: String, default: 'url'},//上传控件模式url,head,variable
        },
        methods: {
          btnChange() {
            var file = document.getElementById('file');
            file.click();
          },
          fileChange(e){
            try {          
              const fu = this.getFile();   
              if(fu==null)return;   
              if(!this.beforeUpload(fu))return;
              if(this.autoUpload){
                this.submit(fu);
              }else{
                if(this.upMode=='url')return; 
                //本地预览
                var reader = new FileReader();
                reader.readAsDataURL(fu);                    
                reader.onload = function(e) {
                  var src = this.result;
                  var str = '<img src="'+src+'">';
                  var target=this.upMode=='head'?'.el-upload--picture-card':'.el-upload-dragger';
                  var nim = document.querySelector(target);
                  if(nim) {
                    nim.innerHTML='';
                    nim.insertAdjacentHTML("beforeEnd", str)
                  }
                };
              }
                
            } catch (error) {
              console.debug('choice file err:',error);
            }
          },
          beforeUpload(f) {
            const maxSzie = glob.Config.UploadSize;
            if (f.size/1024/1024 > maxSzie) {
              this.$message.error('上传文件大小不能超过'+maxSzie+'M.');
              return false;
            }
            var types = glob.Config.UploadType;
            for (let i = 0; i < types.length; i++) {
              if(types[i]===f.type) return true;          
            }
            this.$message.error('上传文件格式不允许!');
            return false;
          },
          uploadClick(e){
            this.submit();
          },
          submit(file){
          try {
            if(!file) file = this.getFile();
            if(file==null)return;
            var isUpload =true;
            this.$emit('onbefore', file);
            if(!isUpload)return;
            const url =process.env.Store_API + this.action;
            var fd = new window.FormData();
            // 配置post请求的参数。参数名fileType,值为category(看后端的具体要求)
            fd.append('fileType', 'category');
            fd.append('file', file);
            var xhr = new XMLHttpRequest();
            xhr.open('POST', url, true);
            xhr.send(fd);
            xhr.onload = () => {
              if (xhr.status === 200) {
                var res = JSON.parse(xhr.responseText);
                if(res.code==1) {
                  var imgurl = glob.StaticStoreHost+res.data;
                  this.$emit('onsuccess', imgurl);
                }else{ 
                  this.$message(res.message);
                }
              }
            }
          } catch (error) {
            console.debug('upload file err:',error);
          }   
          },
          getFile(){
            var file = document.getElementById('file');
            if(file.files.length==0){
              this.$message('没有选择文件');
              return null;
            }
            return file.files[0];
          },
        },    
        
      }
    </script>

    其实就这个小组件就体现到封装、继承、多态的思想,多花时间思考,代码就能简洁、灵活、可用性高。

    样式也有重写,需要样式的评论支持下,谢谢。

  • 相关阅读:
    TS之类的继承
    TS之函数及函数传参
    TS之数据类型
    Linux 协程
    设计模式 装饰器模式和代理模式
    C/C++ C和C++的区别
    C/C++ 内存分配方式
    Linux 进程间通信
    C/C++ RTTI
    Reactor设计模式
  • 原文地址:https://www.cnblogs.com/he-bo/p/11134912.html
Copyright © 2020-2023  润新知