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的值

相关推荐
zhangphil26 分钟前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_5127446426 分钟前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.43 分钟前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao1 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee1 小时前
PHP伪协议总结
android·开发语言·php
mmsx8 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人11 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌12 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习
_Shirley13 小时前
鸿蒙设置app更新跳转华为市场
android·华为·kotlin·harmonyos·鸿蒙
hedalei15 小时前
RK3576 Android14编译OTA包提示java.lang.UnsupportedClassVersionError问题
android·android14·rk3576