vue2组件库-上传组件

news2024/11/16 1:15:49

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1143069.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何中断一个正在运行的线程?

线程 线程是系统级别的概念&#xff0c;在 Java 里面实现的线程&#xff0c;最终的执行和调度都是由操作系统来决定的&#xff0c;JVM 只是对操作系统层面的线程做了一层包装而已。所以我们在 Java 里面通过 start 方法启动一个线程的时候&#xff0c;只是告诉操作系统这个线程…

R语言入门看这一章就够了(上)

目录 一、R的基础 1.1、R的安装 1.2、牛刀小试 1.3、线性关系实例 1.4、工作空间 1.5、R包的使用 包的安装 结果的重用 二、R数据集 2.1、向量 2.2、矩阵 2.3、数组 2.4、数据框 2.5、列表 三、R的常用命令 四、list列表详解 五、数据源导入方法 5.1、键盘输…

黔院长 | 黄帝内经:人有四经十二从!

"人有四经十二从"这句话出自《黄帝内经素问》&#xff0c;“四经”指的是与四时相应的正常脉象&#xff0c;也是指四个主要经络&#xff1a;太阳经、少阳经、太阴经和少阴经。在中医理论当中这些经络被认为是人体气血运行的通道。 而“十二从”则表示人体的十二个经脉…

VulnHub Metasploitable-2

一、信息收集 nmap扫描 访问80端口 二、漏洞利用 1.漏洞一 1.vsftpd 2.3.4&#xff08;CVE-2011-2523&#xff09; 2.msf msf6 > search vsftpd msf6 > use 0 msf6 exploit(unix/ftp/vsftpd_234_backdoor) > set rhosts 192.168.103.189 msf6 exploit(unix/ftp/vs…

ATV32变频器在堆垛机应用

一、机型介绍&#xff1a; 目前国内物流行业发展速度很快&#xff0c;特别是在自动仓库这一块&#xff0c;自动仓库用的最多是堆垛机&#xff0c;自动仓库目前驱动用得基本上变频器。品牌基本是丹佛斯、日系及其他等重载系列变频器。设备主要包括&#xff1a;提升机、货叉及行…

【Java题】输出基本数据类型的最大值和最小值,以及float和double的正无穷大值和负无穷大值

一&#xff1a;代码 public class Test {public static void main(String[] args) {//输出byte型的最大值与最小值System.out.println(Byte.MAX_VALUE);System.out.println(Byte.MIN_VALUE);//输出short型的最大值与最小值System.out.println(Short.MAX_VALUE);System.out.pri…

2023-2024 年最佳 6 款数据恢复软件免费在线下载

如果您正在寻找在线数据恢复工具来帮助自己摆脱数据丢失的麻烦&#xff0c;这篇文章可以为您提供帮助。我们讲解如何免费在线恢复数据&#xff0c;并从兼容性、适用性、易用性、价格等角度分享了市场上六款著名的数据恢复软件。每个在线恢复工具都是安全的&#xff0c;并且可以…

植物大战僵尸 forMac/Windows系统中文版:一场惊心动魄的生存之战

在充满惊喜与挑战的《植物大战僵尸》游戏中&#xff0c;一场奇妙的生存之战正等待着你。为了保护你的大脑&#xff0c;你必须组建一支植物军队&#xff0c;利用各种独特的植物和能力&#xff0c;抵御一波又一波的僵尸大军。现在就让我们深入了解这款引人入胜的游戏&#xff0c;…

【C++】Linux下如何查看opencv的版本

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

Bootstrap的咖啡网站实例代码阅读笔记

目录 01-index.html的完整代码02-图片可以通过类 rounded-circle 设置为圆形显示03-<li class"nav-item mt-1 a">中&#xff0c;类mt-1是什么意思&#xff1f;类a又是什么意思&#xff1f;04-href"javascript:void(0);"是什么意思&#xff1f;05-类f…

Java 浅拷贝会带来的问题

Java 浅拷贝会带来的问题 一&#xff0c;常见问题 Java 中的浅拷贝是指在对象拷贝时&#xff0c;只复制对象的引用&#xff0c;而不是对象本身。这意味着浅拷贝会导致多个对象共享同一块内存空间&#xff0c;当一个对象修改共享内存时&#xff0c;其他对象也会受到影响。 下…

Ubuntu下使用Docker的简单命令

1&#xff1a;要在Ubuntu下使用Docker首先需要提权&#xff0c;Ubuntu下root是没有密码的。注意前导符的变化$是普通用户&#xff0c;#是管理员。 sudo -i2&#xff1a;运行一个容器。-d是后台运行&#xff0c;-p是把http的端口号由80变成8080。 docker run -d -p 8080:80 ht…

php之 角色的权限管理(RBAC)详解

RBAC&#xff08;Role-based access control&#xff09;是一种常见的权限管理模型&#xff0c;通过将用户分配至特定的角色&#xff0c;以及为角色分配访问权限&#xff0c;实现了权限管理的目的。以下是关于RBAC的详细解释&#xff1a; 角色&#xff1a;RBAC模型的核心是角色…

[RISC-V]verilog

小明教IC-1天学会verilog(7)_哔哩哔哩_bilibili task不可综合&#xff0c;function可以综合

FL Studio21水果编曲软件如何切换成官方中文版

FL studio又被国内网友称之为水果音乐制作软件21版本&#xff0c;是Image-Line公司成立23周年而发布的一个版本&#xff0c;FL studio中文版是目前互联网上最优秀的完整的软件音乐制作环境或数字音频工作站&#xff0c;FL Studio包含了编排&#xff0c;录制&#xff0c;编辑&am…

面试题:百万数据的导入导出解决方案,怎么设计?

文章目录 前景1 传统POI的的版本优缺点比较HSSFWorkbookXSSFWorkbookSXSSFWorkbook 2 使用方式哪种看情况3 百万数据导入导出&#xff08;正菜&#xff09;想要解决问题我们首先要明白自己遇到的问题是什么&#xff1f;解决思路&#xff1a;3.1 EasyExcel 简介3.2 300w数据导出…

P1494 [国家集训队] 小 Z 的袜子

这一题是一个关于多次查询区间状态的一个问题&#xff0c;暴力肯定会超限&#xff0c;但是可以用莫队来优化暴力。 莫队的思想就是&#xff0c;用上一个区间的状态来更新当前区间的状态。 问题就是状态怎么更新以及求出当前区间的状态、也就是有多少对相同的袜子以及总共有多…

禁止chrome浏览器更新方式

1、禁用更新服务 WinR调出运行&#xff0c;输入services.msc&#xff0c;进入服务。 在服务中有两个带有Google Update字样&#xff0c;双击打开后禁用&#xff0c;并把恢复选项设置为无操作。 2、删除计划任务 运行taskschd.msc&#xff0c;打开计划任务程序库&#xff0c;在…

uniapp 中添加 vconsole

uniapp 中添加 vconsole 一、安装 vconsole npm i vconsole二、使用 vconsole 在项目的 main.js 文件中添加如下内容 // #ifdef H5 // 提交前需要注释 本地调试使用 import * as vconsole from "vconsole"; new vconsole() // 使用 vconsole // #endif三、成功

Redis中的数据类型及与Mysql数据库同步方法

1.Redis中的数据类型 Redis中的数据类型包括&#xff1a; 排行榜应选用有序集合Zset&#xff0c;原因是排行榜既要去重&#xff0c;也要排序&#xff0c;用这种结构最为合适。 2.Redis和MySQL之间的同步常见方法 要实现Redis和MySQL之间的同步&#xff0c;常见方法包括&…