≡
  • 网络编程
  • 数据库
  • CMS技巧
  • 软件编程
  • PHP笔记
  • JavaScript
  • MySQL
位置:首页 > 网络编程 > vue.js

Vue的移动端多图上传插件vue-easy-uploader的示例代码

人气:442 时间:2019-04-08

这篇文章主要为大家详细介绍了Vue的移动端多图上传插件vue-easy-uploader的示例代码,具有一定的参考价值,可以用来参考一下。

感兴趣的小伙伴,下面一起跟随四海网的小编两巴掌来看看吧!

 

前言

 

这段时间赶项目,需要用到多文件上传,用Vue进行前端项目开发。在网上找了不少插件,都不是十分满意,有的使用起来繁琐,有的不能适应本项目。就打算自己折腾一下,写一个Vue的上传插件,一劳永逸,以后可以直接使用。

目前vue-easy-uploader已上传到GitHub和NPM,使用起来方便简单,不需要繁琐的配置即可投入生产,不过需要后端配合,实现上传接口。

本项目GitHub地址: https://github.com/quanzaiyu/vue-easy-uploader

本项目NPM地址: https://www.npmjs.com/package/vue-easy-uploader

详细的使用方法都在仓库Readme中,就不赘述,这里谈下本插件的设计开发思路。

 

插件介绍

 

vue-easy-uploader是一个多图上传插件。主要特性包括:

  1. 多文件上传
  2. 上传图片预览
  3. 上传状态监测
  4. 删除指定图片
  5. 清空图片
  6. 重新上传

后期版本迭代将不限于图片,往通用文件上传进行改进。

先看看上传插件使用时候的效果图:

【q1010.com温馨提示:图片暂缺】

目录结构

【q1010.com温馨提示:图片暂缺】

代码如下:


index.js # 主入口文件
store.js # 状态管理
uploader.vue # 上传组件

文件解析

index.js

代码如下:


import uploader from './uploader'
import store from './store'

let plugin = {}

plugin.install = function (_Vue, _store) {
 _Vue.component('uploader', uploader)
 _store.registerModule('imgstore', store)
}

export default plugin

这是插件的主入口文件,注册了全局的上传组件和状态管理,使用时只需要在项目入口文件(一般是main.js)中加入以下代码即可引入此插件:

代码如下:


import Vue from 'vue'
import Vuex from 'vuex'
import uploader from 'vue-easy-uploader'
 
let store = new Vuex.Store({})
Vue.use(uploader, store)

store.js

此文件为状态管理配置文件,主要包含三个state:

代码如下:


img_upload_cache # 上传文件缓存
img_paths # 上传状态,包括 ready selected uploading finished
img_status # 上传后的路径反馈数组(数据结构为Set集合)

针对每个state都有自己的mutation,用于改变state,规范上mutation都需要使用大写字母加下划线的形式,本人习惯使用小写字母,不过都不是原则上的问题。

最重要的一个state是img_status,用于监视图片上传的状态。包括以下几个状态:

代码如下:


ready # 上传开始前的准备状态 
selected # 已选择上传文件 
uploading # 开始上传 
finished # 上传完毕 

在组件中可以通过改变上传状态实现文件的上传,同时也可以监听上传状态的变化而执行回调。如:

代码如下:


methods: {
 upload () {
  this.$store.commit('set_img_status', 'uploading')
 },
 submit () {
  // some code
 }
}
computed: {
 ...mapState({
  imgStatus: state => state.imgstore.img_status
 })
},
watch: {
 imgStatus () {
  if (this.imgStatus === 'finished') {
   this.submit()
  }
 }
}

上述代码中,使用upload方法更新了上传状态,让图片开始执行上传操作,使用watch进行上传状态的监视,当上传完成(img_status状态变为finished),执行回调函数submit。

源文件如下:

代码如下:


// Created by quanzaiyu on 2017/10/25 0025.
var state = {
 img_upload_cache: [],
 img_paths: [],
 img_status: 'ready' // 上传状态 ready selected uploading finished
}

const actions = {}

const getters = {}

const mutations = {
 set_img_upload_cache (state, arg) {
  state.img_upload_cache = arg
 },
 set_img_paths (state, arg) {
  state.img_paths = arg
 },
 set_img_status (state, arg) {
  state.img_status = arg
 }
}

export default {
 state,
 mutations,
 actions,
 getters
}

uploader.vue

先看源代码(为了节省空间,未贴出style部分的代码):

代码如下:


<template>
 <div class="imgUploader">
  <div class="file-list">
   <section
    v-for="(file, index) in imgStore" :key="index"
    class="file-item draggable-item"
   >
    <img :src="file.src" alt="" ondragstart="return false;">
    <span class="file-remove" @click="remove(index)">+</span>
   </section>
   <section class="file-item" v-if="imgStatus !== 'finished'">
    <div class="add">
     <span>+</span>
     <input type="file" pictype='30010003' multiple
      data-role="none" accept="image/*"
      @change="selectImgs"
      ref="file"
     >
    </div>
   </section>
  </div>
  <div class="uploadBtn">
   <section>
    <span v-if="imgStore.length > 0" class="empty"
     @click="empty">
      {{imgStatus === 'finished' ? '重新上传' : '清空'}}
    </span>
   </section>
  </div>
 </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
 props: ['url'],
 data () {
  return {
   files: [], // 文件缓存
   index: 0 // 序列号
  }
 },
 computed: {
  ...mapState({
   imgStore: state => state.imgstore.img_upload_cache,
   imgPaths: state => state.imgstore.img_paths,
   imgStatus: state => state.imgstore.img_status
  })
 },
 methods: {
  // 选择图片
  selectImgs () { # ①
   let fileList = this.$refs.file.files
   for (let i = 0; i < fileList.length; i++) {
    // 文件过滤
    if (fileList[i].name.match(/.jpg|.gif|.png|.bmp/i)) { 
     let item = {
      key: this.index++,
      name: fileList[i].name,
      size: fileList[i].size,
      file: fileList[i]
     }
     // 将图片文件转成BASE64格式
     let reader = new FileReader() # ②
     reader.onload = (e) => {
      this.$set(item, 'src', e.target.result)
     }
     reader.readAsDataURL(fileList[i])
     this.files.push(item)
     this.$store.commit('set_img_upload_cache', this.files) // 存储文件缓存
     this.$store.commit('set_img_status', 'selected') // 更新文件上传状态
    }
   }
  },
  // 上传图片
  submit () {
   let formData = new FormData() # ③
   this.imgStore.forEach((item, index) => {
    item.name = 'imgFiles[' + index + ']' # ④
    formData.append(item.name, item.file)
   })
   formData.forEach((v, k) => console.log(k, ' => ', v))
   // 新建请求
   const xhr = new XMLHttpRequest() # ⑤
   xhr.open('POST', this.url, true)
   xhr.send(formData)
   xhr.onload = () => {
    if (xhr.status === 200 || xhr.status === 304) {
     let datas = JSON.parse(xhr.responseText)
     console.log('response: ', datas)
     // 存储返回的地址
     let imgUrlPaths = new Set()  # ⑥
     datas.forEach(e => { // error === 0为成功状态
      e.error === 0 && imgUrlPaths.add(e.url)
     })
     this.$store.commit('set_img_paths', imgUrlPaths) // 存储返回的地址
     this.files = [] // 清空文件缓存
     this.index = 0 // 初始化序列号
     this.$store.commit('set_img_status', 'finished') // 更新文件上传状态
    } else {
     alert(`${xhr.status} 请求错误!`)
    }
   }
  },
  // 移除图片
  remove (index) {
   this.files.splice(index, 1)
   this.$store.commit('set_img_upload_cache', this.files) // 更新存储文件缓存
  },
  // 清空图片
  empty () {
   this.files.splice(0, this.files.length)
   this.$store.commit('set_img_upload_cache', this.files) // 更新存储文件缓存
   this.$store.commit('set_img_paths', [])
  }
 },
 beforeCreate () {
  this.$store.commit('set_img_status', 'ready') // 更新文件上传状态
 },
 destroyed () {
  this.$store.commit('set_img_upload_cache', [])
  this.$store.commit('set_img_paths', [])
 },
 watch: {
  imgStatus () {
   if (this.imgStatus === 'uploading') {
    this.submit()  # ⑦
   }
  },
  imgStore () {
   if (this.imgStore.length <= 0) {
    this.$store.commit('set_img_status', 'ready') // 更新文件上传状态
   }
  }
 }
}
</script>

<style lang="less" scoped>
...
</style>

以上代码中有一些注释序号,是此插件设计的主要思路,其他代码都比较容易理解,分别说下

① 选择文件后执行,img_status状态变为selected。
② 将带上传的图片文件转化为Base64格式,用于缩略图显示。
③ 创建一个表单对象,用于存储待上传的文件。
④ 注意这里的name属性值,暂时写死,后面设计打算从组件中指定name属性,如果是多文件的话,name属性的数组序号从0开始递增。
⑤ 未依赖任何Ajax请求插件,使用原生的XMLHttpRequest对象创建请求。
⑥ 存储上传成功后服务器返回的上传路径。
⑦ 检测上传状态,当在使用此插件时将img_status的状态设置为uploading时执行上传操作。

使用

参考本项目的GItHub和NPM。

注意

使用此插件时,需要与后端约定返回的数据格式,如下:

 

代码如下:


[{"error":0,"url":"\/uploads\/api\/201711\/25\/fde412bd83d3ec5d6a49769bd0c143cd.jpg"},{"error":0,"url":"\/uploads\/api\/201711\/25\/c6fd51f0388c63a0b6d350331c945fb1.jpg"}]
 

 

预览如下:

【q1010.com温馨提示:图片暂缺】

返回的是一个上传后的路径数组,包括error和url字段,每个文件有自己的上传状态,当error为0的时候为上传成功,并返回上传后的路径url

 

改进

 

后续版本打算进行如下改进

  1. 把表单的name属性名称通过组件传递。
  2. 自定义上传成功后服务器响应的数据格式,比如自定义error的名称和其值所表示的状态。
  3. 支持其他类型文件的上传,可以在组件中自行制定上传的文件类型,及其预览方式。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持四海网。

本文来自:http://www.q1010.com/184/4248-0.html

注:关于Vue的移动端多图上传插件vue-easy-uploader的示例代码的内容就先介绍到这里,更多相关文章的可以留意四海网的其他信息。

关键词:vue.js

您可能感兴趣的文章

  • 浅析Vue自定义组件的v-model
  • 初识 Vue.js 中的 *.Vue文件
  • VueJs 将接口用webpack代理到本地的方法
  • 浅谈vue-cli加载不到dev-server.js的解决办法
  • vue.js开发实现全局调用的MessageBox组件实例代码
  • 浅谈Vue-cli 命令行工具分析
  • vue轮播图插件vue-awesome-swiper
  • Vue代码分割懒加载的实现方法
  • vue-awesome-swiper滑块插件使用方法分析
  • Vue父子模版传值及组件传值的三种方法
上一篇:解读vue生成的文件目录结构及说明
下一篇:Vue父子模版传值及组件传值的三种方法
热门文章
  • Vue 报错TypeError: this.$set is not a function 的解决方法
  • vue实现动态添加数据滚动条自动滚动到底部的示例代码
  • vue项目设置scrollTop不起作用(总结)
  • vue项目中使用vue-i18n报错的解决方法
  • iview实现select tree树形下拉框的示例代码
  • 分析关于element级联选择器数据回显问题
  • vue项目打包后打开页面空白解决办法
  • 解决element ui select下拉框不回显数据问题的解决
  • element-ui table span-method(行合并)的实现代码
  • element-ui 设置菜单栏展开的方法
  • 最新文章
    • 理解vue ssr原理并自己搭建简单的ssr框架
    • vue favicon设置以及动态修改favicon的方法
    • vue-router启用history模式下的开发及非根目录部署方法
    • 从零开始在NPM上发布一个Vue组件的方法步骤
    • Element input树型下拉框的实现代码
    • Vue 报错TypeError: this.$set is not a function 的解决方法
    • Vue.js组件高级特性实例分析
    • 浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
    • 分析Vue.js自定义tipOnce指令用法实例
    • 浅谈vuex actions和mutation的异曲同工

四海网收集整理一些常用的php代码,JS代码,数据库mysql等技术文章。