baiyaaaaa 8 anni fa
parent
commit
2f61998e78

+ 43 - 3
examples/docs/zh-CN/upload.md

@@ -49,6 +49,9 @@
       },
       handleError(err, file, fileList) {
         console.log(err);
+      },
+      submitUpload() {
+        this.$refs.upload.submit();
       }
     }
   }
@@ -69,7 +72,7 @@
   :on-remove="handleRemove"
   :file-list="fileList">
   <el-button size="small" type="primary">点击上传</el-button>
-  <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
+  <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
 </el-upload>
 <script>
   export default {
@@ -95,11 +98,12 @@
 ```html
 <el-upload
   class="upload-demo"
-  dragger
+  draggable
   action="//jsonplaceholder.typicode.com/posts/"
   :on-preview="handlePreview"
   :on-remove="handleRemove"
-  :file-list="fileList">
+  :file-list="fileList"
+  thumbnail-mode>
   <i class="el-icon-upload"></i>
   <div class="el-upload-dragger__text">将文件拖到此处,或<em>点击上传</em></div>
   <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
@@ -107,6 +111,42 @@
 ```
 :::
 
+### 手动上传
+
+::: demo
+```html
+<el-upload
+  class="upload-demo"
+  ref="upload"
+  action="//jsonplaceholder.typicode.com/posts/"
+  :on-preview="handlePreview"
+  :on-remove="handleRemove"
+  :file-list="fileList"
+  :auto-upload="false">
+  <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
+  <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
+  <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
+</el-upload>
+<script>
+  export default {
+    data() {
+      return {
+        fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
+      };
+    },
+    methods: {
+      handleRemove(file, fileList) {
+        console.log(file, fileList);
+      },
+      handlePreview(file) {
+        console.log(file);
+      }
+    }
+  }
+</script>
+```
+:::
+
 <!-- ### 拖拽上传
 
 可将文件拖入指定区域进行上传。

+ 167 - 131
packages/theme-default/src/upload.css

@@ -4,7 +4,7 @@
 
 @component-namespace el {
   @b upload {
-    width: 360px;
+    display: inline-block;
 
     @e input {
       display: none;
@@ -39,7 +39,7 @@
       width: 100%;
       position: relative;
 
-      a {
+      @e name {
         color: var(--color-extra-light-black);
         display: block;
         margin-right: 40px;
@@ -56,6 +56,12 @@
           line-height: inherit;
         }
       }
+      @e icon {
+        position: absolute;
+        right: 0;
+        top: 0;
+        line-height: inherit;
+      }
       & .el-progress {
         position: absolute;
         bottom: -3px;
@@ -74,18 +80,29 @@
       &:hover {
         background-color: var(--color-extra-light-gray);
       }
-      @when finished {
-        & a:hover {
+      @when success {
+        .el-upload__file__icon {
+          color: var(--color-success);
+        }
+        .el-upload__file__name:hover {
           color: var(--link-hover-color);
           cursor: pointer;
         }
         &:hover {
+          .el-upload__file__icon {
+            display: none;
+          }
           .el-upload__btn-delete {
             display: block;
             cursor: pointer;
           }
         }
       }
+      @when fail {
+        .el-upload__file__icon {
+          color: var(--color-error);
+        }
+      }
     }
     @e tip {
       font-size: 12px;
@@ -100,168 +117,187 @@
       color: var(--color-primary);
       display: none;
     }
+    /* 拖拽模式 */
+    @m draggable {
+      background-color: var(--color-dark-white);
+      border: 1px solid var(--color-extra-light-silver);
+      box-sizing: border-box;
+      width: 360px;
+      height: 180px;
+      border-radius: 4px;
+      text-align: center;
+      cursor: pointer;
+      position: relative;
+      overflow: hidden;
+
+      & .el-upload__inner {
+        display: block;
+        height: 100%;
+      }
+      & .el-icon-upload {
+        font-size: 67px;
+        color: var(--color-light-silver);
+        margin: 40px 0 16px;
+        line-height: 50px;
+      }
+
+      & + .el-upload__tip {
+        text-align: center;
+      }
+      & ~ .el-upload__files {
+        margin-top: 7px;
+        padding-top: 5px;
+        border-top: 1px solid rgba(var(--color-extra-light-silver), .2);
+      }
+
+      @e text {
+        color: var(--color-light-silver);
+        font-size: 14px;
+        text-align: center;
+
+        & em {
+          color: var(--color-primary);
+          font-style: normal;
+        }
+      }
+
+      &:not(.is-showCover):hover {
+        border-color: var(--color-primary);
+      }
+
+      @when dragOver {
+        background-color: rgba(32, 159, 255, .06);
+        border: 2px dashed var(--color-primary);
+      }
+    }
   }
-  @b upload-dragger {
-    background-color: var(--color-dark-white);
-    border: 1px solid var(--color-extra-light-silver);
-    box-sizing: border-box;
-    width: 360px;
-    height: 180px;
-    border-radius: 4px;
-    text-align: center;
-    cursor: pointer;
-    position: relative;
+  @b upload-cover {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
     overflow: hidden;
+    z-index: 10;
+    cursor: default;
+    @utils-vertical-center;
 
-    & .el-upload__inner {
+    & img {
       display: block;
+      width: 100%;
       height: 100%;
     }
-    & .el-icon-upload {
-      font-size: 67px;
-      color: var(--color-light-silver);
-      margin: 40px 0 16px;
-      line-height: 50px;
-    }
 
-    & + .el-upload__tip {
+    @e label {
+      position: absolute;
+      right: -15px;
+      top: -6px;
+      width: 40px;
+      height: 24px;
+      background: #13ce66;
       text-align: center;
+      transform: rotate(45deg);
+      box-shadow: 0 0 1pc 1px rgba(0,0,0,0.2);
+
+      i {
+        font-size: 12px;
+        margin-top: 11px;
+        transform: rotate(-45deg) scale(0.8);
+        color: #fff;
+      }
     }
-    & ~ .el-upload__files {
-      margin-top: 7px;
-      padding-top: 5px;
-      border-top: 1px solid rgba(var(--color-extra-light-silver), .2);
+
+    @e progress {
+      display: inline-block;
+      vertical-align: middle;
+      position: static;
+      width: 243px;
+
+      & + .el-upload__inner {
+        opacity: 0;
+      }
     }
 
-    @e cover {
+    @e content {
       position: absolute;
-      left: 0;
       top: 0;
+      left: 0;
       width: 100%;
       height: 100%;
-      overflow: hidden;
-      z-index: 10;
-      cursor: default;
-      @utils-vertical-center;
+    }
 
-      & img {
-        display: block;
-        width: 100%;
-        height: 100%;
-      }
+    @e interact {
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background-color: rgba(#000, .72);
+      text-align: center;
 
-      @e progress {
+      & .btn {
         display: inline-block;
+        color: var(--color-white);
+        font-size: 14px;
+        cursor: pointer;
         vertical-align: middle;
-        position: static;
-        width: 243px;
+        transition: var(--md-fade-transition);
+        margin-top: 60px;
 
-        & + .el-upload__inner {
-          opacity: 0;
+        & i {
+          margin-top: 0;
         }
-      }
 
-      @e content {
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-      }
-
-      @e interact {
-        position: absolute;
-        bottom: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
-        background-color: rgba(#000, .72);
-        text-align: center;
+        & span {
+          opacity: 0;
+          transition: opacity .15s linear;
+        }
 
-        & .btn {
-          display: inline-block;
-          color: var(--color-white);
-          font-size: 14px;
-          cursor: pointer;
-          vertical-align: middle;
-          transition: var(--md-fade-transition);
-          margin-top: 60px;
+        &:not(:first-child) {
+          margin-left: 35px;
+        }
 
-          & i {
-            margin-top: 0;
-          }
+        &:hover {
+          transform: translateY(-13px);
 
           & span {
-            opacity: 0;
-            transition: opacity .15s linear;
-          }
-
-          &:not(:first-child) {
-            margin-left: 35px;
-          }
-
-          &:hover {
-            transform: translateY(-13px);
-
-            & span {
-              opacity: 1;
-            }
-          }
-
-          & i {
-            color: var(--color-white);
-            display: block;
-            font-size: 24px;
-            line-height: inherit;
-            margin: 0 auto 5px;
+            opacity: 1;
           }
         }
-      }
 
-      @e title {
-        position: absolute;
-        bottom: 0;
-        left: 0;
-        background-color: var(--color-white);
-        height: 36px;
-        width: 100%;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        font-weight: normal;
-        text-align: left;
-        padding: 0 10px;
-        margin: 0;
-        line-height: 36px;
-        font-size: 14px;
-        color: var(--color-extra-light-black);
-      }
-
-      & + .el-upload__inner {
-        opacity: 0;
-        position: relative;
-        z-index: 1;
+        & i {
+          color: var(--color-white);
+          display: block;
+          font-size: 24px;
+          line-height: inherit;
+          margin: 0 auto 5px;
+        }
       }
     }
 
-    @e text {
-      color: var(--color-light-silver);
+    @e title {
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      background-color: var(--color-white);
+      height: 36px;
+      width: 100%;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      font-weight: normal;
+      text-align: left;
+      padding: 0 10px;
+      margin: 0;
+      line-height: 36px;
       font-size: 14px;
-      text-align: center;
-
-      & em {
-        color: var(--color-primary);
-        font-style: normal;
-      }
-    }
-
-    &:not(.is-showCover):hover {
-      border-color: var(--color-primary);
+      color: var(--color-extra-light-black);
     }
 
-    @when dragOver {
-      background-color: rgba(32, 159, 255, .06);
-      border: 2px dashed var(--color-primary);
+    & + .el-upload__inner {
+      opacity: 0;
+      position: relative;
+      z-index: 1;
     }
   }
 }

+ 10 - 9
packages/upload/src/cover.vue

@@ -1,32 +1,33 @@
 <template>
-  <div class="el-dragger__cover" @click.stop v-if="image">
+  <div class="el-upload-cover" @click.stop v-if="image">
     <transition name="el-fade-in">
       <el-progress
-        class="el-dragger__cover__progress"
+        class="el-upload-cover__progress"
         v-if="image.status === 'uploading'"
         :percentage="image.percentage"
         :show-text="false"
-        :status="image.status === 'finished' ? 'success' : ''">
+      >
       </el-progress>
     </transition>
     <div
-      class="el-dragger__cover__content"
-      v-if="image.status === 'finished'"
+      class="el-upload-cover__content"
+      v-if="image.status === 'success'"
       @mouseenter="mouseover = true"
       @mouseleave="mouseover = false"
     >
       <img :src="image.url">
+      <label class="el-upload-cover__label"><i class="el-icon-check"></i></label>
       <transition name="el-fade-in">
-        <div v-show="mouseover" class="el-dragger__cover__interact">
+        <div v-show="mouseover" class="el-upload-cover__interact">
           <div class="el-draggeer__cover__btns">
             <span class="btn" @click="$parent.handleClick()"><i class="el-icon-upload2"></i><span>{{ t('el.upload.continue') }}</span></span>
-            <span class="btn" @click="onPreview(image)"><i class="el-icon-view"></i><span>{{ t('el.upload.preview') }}</span></span>
-            <span class="btn" @click="onRemove(image)"><i class="el-icon-delete2"></i><span>{{ t('el.upload.delete') }}</span></span>
+            <span class="btn" @click="$emit('preview', image)"><i class="el-icon-view"></i><span>{{ t('el.upload.preview') }}</span></span>
+            <span class="btn" @click="$emit('remove', image)"><i class="el-icon-delete2"></i><span>{{ t('el.upload.delete') }}</span></span>
           </div>
         </div>
       </transition>
       <transition name="el-zoom-in-bottom">
-        <h4 v-show="mouseover" class="el-dragger__cover__title">{{image.name}}</h4>
+        <h4 v-show="mouseover" class="el-upload-cover__title">{{image.name}}</h4>
       </transition>
     </div>
   </div>

+ 30 - 0
packages/upload/src/dragger.js

@@ -0,0 +1,30 @@
+import Cover from './cover';
+
+export default {
+  components: {
+    Cover
+  },
+  data() {
+    return {
+      dragOver: false
+    };
+  },
+  computed: {
+    lastestFile() {
+      return this.fileList[this.fileList.length - 1];
+    },
+    showCover() {
+      var file = this.lastestFile;
+      return this.thumbnailMode && file && file.status !== 'fail';
+    },
+    thumbnailMode() {
+      return this.$parent.thumbnailMode;
+    }
+  },
+  methods: {
+    onDrop(e) {
+      this.dragOver = false;
+      this.uploadFiles(e.dataTransfer.files);
+    }
+  }
+};

+ 1 - 1
packages/upload/src/iframe-upload.vue

@@ -160,7 +160,7 @@ export default {
           </input>
           <input type="hidden" name="documentDomain" value={ this.$isServer ? '' : document.domain } />
           <span ref="data"></span>
-         </form>
+        </form>
         {!this.showCover ? this.$slots.default : cover}
       </div>
     );

+ 49 - 65
packages/upload/src/index.vue

@@ -5,8 +5,7 @@ import UploadDragger from './upload-dragger';
 import IframeUpload from './iframe-upload';
 import ElProgress from 'element-ui/packages/progress';
 
-function noop() {
-}
+function noop() {}
 
 export default {
   name: 'ElUpload',
@@ -79,6 +78,10 @@ export default {
       default() {
         return [];
       }
+    },
+    autoUpload: {
+      type: Boolean,
+      default: true
     }
   },
 
@@ -96,78 +99,71 @@ export default {
       immediate: true,
       handler(fileList) {
         this.uploadFiles = fileList.map(item => {
-          if (!item.uid) {
-            item.uid = Date.now() + this.tempIndex++;
-          }
+          item.uid = item.uid || (Date.now() + this.tempIndex++);
+          item.status = 'success';
           return item;
         });
       }
-    },
-    uploadFiles(value, oldValue) {
-      // console.log(value, oldValue);
     }
   },
 
   methods: {
-    handleStart(file) {
-      file.uid = Date.now() + this.tempIndex++;
-      let _file = {
-        status: 'uploading',
-        name: file.name,
-        size: file.size,
+    handleStart(rawFile) {
+      rawFile.uid = Date.now() + this.tempIndex++;
+      let file = {
+        status: 'ready',
+        name: rawFile.name,
+        size: rawFile.size,
         percentage: 0,
-        uid: file.uid,
-        showProgress: true
+        uid: rawFile.uid,
+        raw: rawFile
       };
 
       try {
-        _file.url = URL.createObjectURL(file);
+        file.url = URL.createObjectURL(rawFile);
       } catch (err) {
         console.error(err);
         return;
       }
 
-      this.uploadFiles.push(_file);
+      this.uploadFiles.push(file);
     },
-    handleProgress(ev, file) {
-      var _file = this.getFile(file);
-      this.onProgress(ev, _file, this.uploadFiles);
-      _file.percentage = ev.percent || 0;
+    handleProgress(ev, rawFile) {
+      var file = this.getFile(rawFile);
+      this.onProgress(ev, file, this.uploadFiles);
+      file.status = 'uploading';
+      file.percentage = ev.percent || 0;
     },
-    handleSuccess(res, file) {
-      var _file = this.getFile(file);
+    handleSuccess(res, rawFile) {
+      var file = this.getFile(rawFile);
 
-      if (_file) {
-        _file.status = 'finished';
-        _file.response = res;
+      if (file) {
+        file.status = 'success';
+        file.response = res;
 
-        this.onSuccess(res, _file, this.uploadFiles);
-
-        setTimeout(() => {
-          _file.showProgress = false;
-        }, 1000);
+        this.onSuccess(res, file, this.uploadFiles);
       }
     },
-    handleError(err, response, file) {
-      var _file = this.getFile(file);
+    handleError(err, response, rawFile) {
+      var file = this.getFile(rawFile);
       var fileList = this.uploadFiles;
 
-      _file.status = 'fail';
+      file.status = 'fail';
 
-      fileList.splice(fileList.indexOf(_file), 1);
+      fileList.splice(fileList.indexOf(file), 1);
 
-      this.onError(err, response, file);
+      this.onError(err, response, rawFile);
     },
     handleRemove(file) {
       var fileList = this.uploadFiles;
       fileList.splice(fileList.indexOf(file), 1);
       this.onRemove(file, fileList);
     },
-    getFile(file) {
+    getFile(rawFile) {
       var fileList = this.uploadFiles;
       var target;
       fileList.every(item => {
-        target = file.uid === item.uid ? item : null;
+        target = rawFile.uid === item.uid ? item : null;
         return !target;
       });
       return target;
@@ -180,34 +176,19 @@ export default {
     clearFiles() {
       this.uploadFiles = [];
     },
-    initDraggable() {
-      const target = this.$el;
-      const _this = this;
-      target.addEventListener('dragover', event => {
-        event.preventDefault();
-        _this.draggable = true;
-      });
-      target.addEventListener('drop', event => {
-        event.preventDefault();
-        _this.draggable = false;
-      });
-      target.addEventListener('dragleave', event => {
-        event.preventDefault();
-        _this.draggable = false;
-      });
-    }
-  },
-
-  mounted() {
-    if (this.draggable) {
-      this.initDraggable();
+    submit() {
+      this.uploadFiles
+        .filter(file => file.status === 'ready')
+        .forEach(file => {
+          this.$refs['upload-inner'].upload(file.raw, file);
+        });
     }
   },
 
   render(h) {
     var uploadList;
 
-    if (this.showUploadList && !this.thumbnailMode && this.uploadFiles.length) {
+    if (this.showUploadList && this.uploadFiles.length) {
       uploadList = (
         <UploadList
           files={this.uploadFiles}
@@ -217,7 +198,7 @@ export default {
       );
     }
 
-    var props = {
+    var uploadData = {
       props: {
         type: this.type,
         draggable: this.draggable,
@@ -229,6 +210,8 @@ export default {
         name: this.name,
         data: this.data,
         accept: this.thumbnailMode ? 'image/gif, image/png, image/jpeg, image/bmp, image/webp' : this.accept,
+        fileList: this.uploadFiles,
+        autoUpload: this.autoUpload,
         'on-start': this.handleStart,
         'on-progress': this.handleProgress,
         'on-success': this.handleSuccess,
@@ -243,10 +226,10 @@ export default {
     //     ? <upload {...props}>{this.$slots.default}</upload>
     //     : <iframeUpload {...props}>{this.$slots.default}</iframeUpload>;
 
-    if (this.dragger) {
+    if (this.draggable) {
       return (
         <div>
-          <upload-dragger {...props}>{this.$slots.default}</upload-dragger>
+          <upload {...uploadData}>{this.$slots.trigger || this.$slots.default}</upload>
           {this.$slots.tip}
           {uploadList}
         </div>
@@ -256,7 +239,8 @@ export default {
     return (
       <div>
         {uploadList}
-        <upload {...props}>{this.$slots.default}</upload>
+        <upload {...uploadData}>{this.$slots.trigger || this.$slots.default}</upload>
+        {this.$slots.default}
         {this.$slots.tip}
       </div>
     );

+ 9 - 8
packages/upload/src/upload-list.vue

@@ -2,22 +2,23 @@
   <transition-group tag="ul" class="el-upload__files" name="list">
     <li
       v-for="file in files"
-      class="el-upload__file"
-      :class="{
-        'is-finished': file.status === 'finished'
-      }"
+      :class="['el-upload__file', 'is-' + file.status]"
       :key="file"
       @click="$emit('clickFile', file)"
     >
       <a class="el-upload__file__name" @click="$emit('preview', file)">
         <i class="el-icon-document"></i>{{file.name}}
       </a>
-      <span class="el-upload__btn-delete" @click="$emit('remove', file)" v-show="file.status === 'finished'">{{ t('el.upload.delete') }}</span>
+      <i :class="{
+        'el-upload__file__icon': true,
+        'el-icon-circle-check': file.status === 'success',
+        'el-icon-circle-cross': file.status === 'fail'
+      }"></i>
+      <span class="el-upload__btn-delete" @click="$emit('remove', file)" v-show="file.status === 'success'">{{ t('el.upload.delete') }}</span>
       <el-progress
-        v-if="file.showProgress"
+        v-if="file.status === 'uploading'"
         :stroke-width="2"
-        :percentage="parsePercentage(file.percentage)"
-        :status="file.status === 'finished' && file.showProgress ? 'success' : ''">
+        :percentage="parsePercentage(file.percentage)">
       </el-progress>
     </li>
   </transition-group>

+ 79 - 36
packages/upload/src/upload.vue

@@ -1,16 +1,11 @@
-<template>
-  <div class="el-upload" @click="handleClick">
-    <slot></slot>
-    <input class="el-upload__input" type="file" ref="input" @change="handleChange" :multiple="multiple" :accept="accept">
-  </div>
-</template>
-
 <script>
+import merge from 'element-ui/src/utils/merge';
 import ajax from './ajax';
+import dragger from './dragger';
 
 export default {
-  components: {
-  },
+  mixins: [dragger],
+
   props: {
     type: String,
     action: {
@@ -31,6 +26,7 @@ export default {
     onSuccess: Function,
     onError: Function,
     beforeUpload: Function,
+    draggable: Boolean,
     onPreview: {
       type: Function,
       default: function() {}
@@ -38,7 +34,9 @@ export default {
     onRemove: {
       type: Function,
       default: function() {}
-    }
+    },
+    fileList: Array,
+    autoUpload: Boolean
   },
 
   data() {
@@ -54,9 +52,7 @@ export default {
     handleChange(ev) {
       const files = ev.target.files;
 
-      if (!files) {
-        return;
-      }
+      if (!files) return;
       this.uploadFiles(files);
       this.$refs.input.value = null;
     },
@@ -66,64 +62,111 @@ export default {
 
       if (postFiles.length === 0) { return; }
 
-      postFiles.forEach(file => {
-        let isImage = this.isImage(file.type);
-
-        if (this.thumbnailMode && !isImage) {
-          return;
-        } else {
-          this.upload(file);
+      postFiles.forEach(rawFile => {
+        if (!this.thumbnailMode || this.isImage(rawFile.type)) {
+          this.onStart(rawFile);
+          if (this.autoUpload) this.upload(rawFile);
         }
       });
     },
-    upload(file) {
+    upload(rawFile, file) {
       if (!this.beforeUpload) {
-        return this.post(file);
+        return this.post(rawFile);
       }
 
-      const before = this.beforeUpload(file);
+      const before = this.beforeUpload(rawFile);
       if (before && before.then) {
         before.then(processedFile => {
           if (Object.prototype.toString.call(processedFile) === '[object File]') {
             this.post(processedFile);
           } else {
-            this.post(file);
+            this.post(rawFile);
           }
         }, () => {
-          // this.$emit('cancel', file);
+          if (file) this.onRemove(file);
         });
       } else if (before !== false) {
-        this.post(file);
+        this.post(rawFile);
       } else {
-        // this.$emit('cancel', file);
+        if (file) this.onRemove(file);
       }
     },
-    post(file) {
-      this.onStart(file);
-      let formData = new FormData();
-      formData.append(this.name, file);
-
+    post(rawFile) {
       ajax({
         headers: this.headers,
         withCredentials: this.withCredentials,
-        file: file,
+        file: rawFile,
         data: this.data,
         filename: this.name,
         action: this.action,
         onProgress: e => {
-          this.onProgress(e, file);
+          this.onProgress(e, rawFile);
         },
         onSuccess: res => {
-          this.onSuccess(res, file);
+          this.onSuccess(res, rawFile);
         },
         onError: (err, response) => {
-          this.onError(err, response, file);
+          this.onError(err, response, rawFile);
         }
       });
     },
     handleClick() {
       this.$refs.input.click();
     }
+  },
+
+  render(h) {
+    let {
+      handleClick,
+      draggable,
+      onDrop,
+      showCover,
+      onPreview,
+      onRemove,
+      handleChange,
+      multiple,
+      accept,
+      lastestFile
+    } = this;
+    const data = {
+      class: {
+        'el-upload': true
+      },
+      on: {
+        click: handleClick
+      }
+    };
+    if (draggable) {
+      merge(data.on, {
+        dragover: (ev) => {
+          ev.preventDefault();
+          this.dragOver = true;
+        },
+        dragleave: (ev) => {
+          ev.preventDefault();
+          this.dragOver = false;
+        },
+        drop: (ev) => {
+          ev.preventDefault();
+          onDrop(ev);
+        }
+      });
+      merge(data.class, {
+        'el-upload--draggable': true,
+        'is-dragOver': this.dragOver,
+        'is-showCover': this.showCover
+      });
+    }
+    return (
+      <div {...data}>
+        {
+          showCover
+          ? <cover image={lastestFile} on-preview={onPreview} on-remove={onRemove}></cover>
+          : this.$slots.default
+        }
+        <input class="el-upload__input" type="file" ref="input" on-change={handleChange} multiple={multiple} accept={accept}></input>
+      </div>
+    );
   }
 };
 </script>

+ 1 - 0
src/index.js

@@ -109,6 +109,7 @@ const components = [
   Row,
   Col,
   Upload,
+  UploadDragger,
   Progress,
   Spinner,
   Badge,