vue2组件库-上传组件

vue2组件库

上传组件

核心思路: 监控整个上传的流程

上传成功 上传失败

类型:拖拽 多个文件上传

上传必备属性 & 钩子属性

跟上传强关联的属性,上传必备的字段

name: 提交的那个formData字段名

action:ajax接口路径

limit:限制提交个数

钩子函数

上传fileList数据构造

dom: this.$refs

选中文件 上传

按照整个上传的流程

fileList中每个对象的状态

  1. 刚放进去,准备好了待上传
  2. 上传中
  3. 上传完成

自己创建的一个文件对象

数据层fileList

弄一个数据同步v-model或.async,我就给你一个数据不希望它有什么同步的功能 ,我自己身上有一份数据,用户的数据也格式化放到这个数组里不涉及什么子改父父改子,自己处理自己的数据。

文件变化了,触发文件变化的钩子。

发起ajax上传请求

httpPost的处理

处理上传前+上传中+上传成功的各状态展示

file.status percent

onProgress onSuccess onError

upload.vue

复制代码
<template>`
`  <div class="zh-upload">`
`    <div class="zh-upload-button" @click="upload">`
`      <slot></slot>`
`    </div>`
`    <div><slot name="tip"></slot></div>`
`    <input ref="file" type="file" :accept="accept" :multiple="multiple" @change="changeFile">`
`    <ul>`
`      <li v-for="file in files">`
`        {{file.name}}`
`        <zh-progress v-if="file.status==='uploading'" :percent="file.percent"></zh-progress>`
`      </li>`
`    </ul>`
`  </div>`
`</template>`

`<script>`
`import _ from 'lodash'`
`import {ajax} from './upload'`
`export default {`
`  name:'zh-upload',`
`  props:{`
`    name:{`
`      type:String,`
`      default:'file'`
`    },`
`    action:{`
`      type:String,`
`      default:''`
`    },`
`    accept:{`
`      type:String,`
`      default:''`
`    },`
`    multiple:{`
`      type:Boolean,`
`      default:false`
`    },`
`    limit:{`
`      type:Number,`
`      default:0`
`    },`
`    onExceed:{`
`      type:Function,`
`    },`
`    beforeUpload:{`
`      type:Function,`
`    },`
`    httpRequest:{`
`      type:Function,`
`      default:ajax,`
`    },`
`    fileList:{`
`      type:Array,`
`      default:[]`
`    }`
`  },`
`  data(){`
`    return {`
`      files:[],`
`      uniqueId:1,`
`    }`
`  },`
`  watch:{`
`    fileList:{`
`      deep:true,`
`      immediate:true,`
`      handler(val){`
`        this.files=val.map(item=>{`
`          item.uid=`${+new Date}${this.uniqueId++}``
`          item.status='success'`
`          return item;`
`          // const file={`
`          //   uid:item.uid,`
`          //   name:item.name,`
`          //   url:item.url,`
`          //   status:'success', // 完成成功态时只关心 name & url`
`          //   percent:0,`
`          // }`
`          // return file;`
`        })`
`      }`
`    }`
`  },`
`  methods:{`
`    upload(){`
`      this.$refs.file.value=''`
`      this.$refs.file.click()`
`    },`
`    changeFile(ev){`
`      let files=ev.target.files;`
`      // 限制最多上传的文件数`
`      if(this.limit && this.files.length+files.length>this.limit){`
`        return this.onExceed();`
`      }`
`      // [...files].forEach`
`      _.forEach(files,rawFile=>{`
`        this.uploadStart(rawFile)`
`        this.uploadFile(rawFile)`
`      })`
`    },`
`    uploadStart(rawFile){`
`      rawFile.uid=`${+new Date}${this.uniqueId++}``
`      // 构造新的文件对象`
`      const fileNew={`
`        uid:rawFile.uid,`
`        name:rawFile.name,`
`        size:rawFile.size,`
`        type:rawFile.type,`
`        status:'uploadstart',`
`        percent:0,`
`        rawFile,`
`      }`
`      this.files.push(fileNew)`

`    },`
`    uploadFile(rawFile){`
`      // @todo beforeUpload`
`      if(typeof this.beforeUpload === 'function'){`
`        let flag=this.beforeUpload(rawFile) // 目前没考虑promise的情况`
`        if(!flag) return`
`      }`
`      this.post(rawFile)`
`    },`
`    post(rawFile){`
`      const options={`
`        filename:this.name,`
`        file:rawFile,`
`        action:this.action,`
`        onSuccess:(res)=>{`
`          this.handleSuccess(res,rawFile)`

`        },`
`        onError:(res)=>{`

`        },`
`        onProgress:(ev)=>{`
`          this.handleProgress(ev,rawFile)`
`        },`
`      }`
`      this.httpRequest(options)`
`    },`
`    handleSuccess(res,rawFile){`
`      const file=this.files.find(f=>f.uid===rawFile.uid)`
`      file.status='success'`
`    },`
`    handleProgress(ev,rawFile){`
`      // file是原生file文件,找到files中对应的file对象`
`      const file=this.files.find(f=>f.uid===rawFile.uid)`
`      file.status='uploading'`
`      file.percent=Math.round(ev.loaded/ev.total*100)`

`    }`
`  }`
`}`
`</script>`

`<style scoped lang="scss">`
`.zh-upload{`
`  &-button{`
`    display: inline-block;`
`  }`
`  input[type=file]{`
`    display: none;`
`  }`
`}`
`</style>`

`

upload.js

复制代码
export function ajax(options){`
`    let xhr=new XMLHttpRequest()`
`    const {filename,file,action,onSuccess,onError,onProgress}=options;`
`    const fd=new FormData`
`    fd.append(filename,file)`
`    xhr.open('post',action)`
`    xhr.onload=()=>{`
`        onSuccess(JSON.parse(xhr.responseText))`
`    }`
`    xhr.onerror=()=>{`
`        onError(JSON.parse(xhr.errorText))`
`    }`
`    xhr.upload.onprogress=(ev)=>{`
`        onProgress(ev)`
`    }`
`    xhr.send(fd)`
`    return xhr;`
`}`

`

progress.vue

复制代码
<template>`
`<div class="progress-outer" :style="outerStyle">`
`  <div class="progress-inner" :style="innerStyle"></div>`
`</div>`
`</template>`

`<script>`
`export default {`
`  name:'zh-progress',`
`  props:{`
`    strokeWidth:{`
`      type:Number,`
`      default:10`
`    },`
`    strokeColor:{`
`      type:String,`
`      default:'blue'`
`    },`
`    percent:{`
`      type:Number,`
`      default:0`
`    }`
`  },`
`  computed:{`
`    outerStyle(){`
`      return {`
`        height:`${this.strokeWidth}px`,`
`      }`
`    },`
`    innerStyle(){`
`      return {`
`        width:`${this.percent}%`,`
`        background:this.strokeColor`
`      }`
`    }`
`  },`
`  watch:{`
`    percent(val){`
`      console.log(val,'percent');`
`    }`
`  }`
`}`
`</script>`

`<style scoped lang="scss">`
`.progress-outer{`
`  width: 100%;`
`  background: grey;`
`  position: relative;`
`  .progress-inner{`
`    position: absolute;`
`    left: 0;`
`    top: 0;`
`    height: 100%;`
`    transition:width .3s ease;`
`  }`
`}`
`.progress-outer,.progress-inner{`
`  border-radius: 5px;`
`}`
`</style>`

`

设计组件思想:

用户要有那些功能

暴露用户那些功能

用户有哪些行为

拖拽上传

主要就是onDrop事件

ondragover.prevent ondragleave.prevent

Popover组件

appendChild insertBefore都会对dom有移动性

事件:事件机制谁在谁里面,怎么触发这个事件,事件都有哪些问题

具体位置:用js算left top的值

相关推荐
Dingdangr4 小时前
Android中的Intent的作用
android
技术无疆4 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
GEEKVIP4 小时前
Android 恢复挑战和解决方案:如何从 Android 设备恢复删除的文件
android·笔记·安全·macos·智能手机·电脑·笔记本电脑
Jouzzy11 小时前
【Android安全】Ubuntu 16.04安装GDB和GEF
android·ubuntu·gdb
极客先躯11 小时前
java和kotlin 可以同时运行吗
android·java·开发语言·kotlin·同时运行
Good_tea_h14 小时前
Android中的单例模式
android·单例模式
陶甜也18 小时前
前后端分离,使用MOCK进行数据模拟开发,让前端攻城师独立于后端进行开发
前端·okhttp
计算机源码社18 小时前
分享一个基于微信小程序的居家养老服务小程序 养老服务预约安卓app uniapp(源码、调试、LW、开题、PPT)
android·微信小程序·uni-app·毕业设计项目·毕业设计源码·计算机课程设计·计算机毕业设计开题
丶白泽19 小时前
重修设计模式-结构型-门面模式
android
晨春计20 小时前
【git】
android·linux·git