Original address
Objective
This period of time to catch the project, need to use a multi-file upload, with Vue for front-end project development. On the internet to find a lot of plug-ins, are not very satisfied, some use cumbersome, and some can not adapt to the project. Just want to toss a bit, write a Vue upload plugin, once and for all, can be used directly later.
vue-easy-uploader
has been uploaded to GitHub
and NPM
, the use of convenient and simple, do not need cumbersome configuration can be put into production, but need back-end coordination, implementation of the upload interface.
This project GitHub address: Https://github.com/quanzaiyu/vue-easy-uploader
This project NPM address: Https://www.npmjs.com/package/vue-easy-uploader
Detailed use of the method are in the warehouse Readme, do not repeat, here talk about the plug-in design and development ideas.
Plugin Introduction
vue-easy-uploader
is a multi-image upload plugin. Key features include:
- Multiple file uploads
- Upload Picture preview
- Upload Status Monitoring
- Delete a specified picture
- Empty picture
- Re-upload
Later versions of iterations will not be limited to images, and improvements to generic file uploads.
First look at the upload plugin use time:
Directory structure
index.js # 主入口文件store.js # 状态管理uploader.vue # 上传组件
File parsing 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
This is the main portal file of the plug-in, registering the global upload component and state management, use only need to add the following code in the project portal file (typically main.js
) to introduce this plug-in:
importfrom‘vue‘importfrom‘vuex‘importfrom‘vue-easy-uploader‘let=newVuex.Store({})Vue.use(uploader, store)
Store.js
This file is a status management profile and consists of three main state
:
img_upload_cache# 上传文件缓存img_paths# 上传状态,包括 ready selected uploading finishedimg_status# 上传后的路径反馈数组(数据结构为Set集合)
For each state
has its own mutation
, for the change state
, the specification mutation
needs to use capital letters underlined form, I used to use lowercase letters, but are not in principle the problem.
The most important one state
is to img_status
monitor the status of picture uploads. The following States are included:
ready# 上传开始前的准备状态 selected# 已选择上传文件 uploading# 开始上传 finished# 上传完毕
In the component can upload the file by changing the upload status, but also can listen to the upload status changes and execute callbacks. Such as:
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()} }}
In the code above, the upload status is updated using the method, the upload
image is started to perform the upload operation, the upload watch
status is monitored, and when the upload is complete (the img_status
status becomes finished
), the callback function is executed submit
.
The source files are as follows:
//Created by Quanzaiyu on 2017/10/25 0025.varState= { Img_upload_cache:[], img_paths:[], Img_status: ' Ready ' //Upload status Ready selected uploading finished}ConstActions= {}ConstGetters= {}ConstMutations= { 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
First look at the source code (in order to save space, do not post style
part of the code):
<template> <div class= "Imguploader" > <div class= "file-list" > <section v-for= "(File, I Ndex) in Imgstore ": key=" index "class=" File-item draggable-item "> <span class= "file-remove" @click = "Remove (index)" >+</span> </section> <section C lass= "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" & Gt {{Imgstatus = = = ' finished '? ' Re-upload ': ' Empty '} </span> </section> </div> </diV></template><script>import {mapstate} from ' Vuex ' export default {props: [' url '], data () {return {files: [],//File cache index:0//serial Number}}, computed: {... mapstate ({imgstore:state = state.img Store.img_upload_cache, imgpaths:state = state.imgstore.img_paths, imgstatus:state = state.imgstore.im G_status})}, methods: {//Select Picture Selectimgs () {#①let fileList = this. $refs. File.files for (Let I = 0; i < filelist.length; i++) {//File filter if (Filelist[i].name.match (/.jpg|). Gif|. Png|. bmp/i) {Let item = {key:this.index++, name:filelist[i].name, Size:filelis T[i].size, File:filelist[i]}//Convert picture file to BASE64 format let reader = new FileReader () #② Reader.onload = (e) + = {this. $set (item, ' src ', E.target.result)} Reader.readas Dataurl (Filelist[i]) This.files.puSH (item) this. $store. Commit (' Set_img_upload_cache ', this.files)//Store file cache this. $store. Commit (' Set_img_st ATUs ', ' selected ')//update file upload Status}},//upload image 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)//new request Const XHR = NE W XMLHttpRequest () #⑤xhr.open (' POST ', This.url, True) xhr.send (formData) xhr.onload = () = { if (xhr.status = = = | | xhr.status = = 304) {Let datas = Json.parse (xhr.responsetext) console.log (' re Sponse: ', datas)//Store return address let imgurlpaths = new Set () #⑥datas.foreach (E = {//Error = = = 0 for success Status E.error = = = 0 && imgurlpaths.add (e.url)}) this. $store. Commit (' Set_img_pa Ths ', imgurlpaths)//Storagereturn address this.files = []//empty file Cache This.index = 0//Initialize serial number this. $store. Commit (' set_img_status ', ' Finished ')//update file upload status} else {alert (' ${xhr.status} request Error! ')}}},//Remove picture Remove (i Ndex) {this.files.splice (index, 1) this. $store. Commit (' Set_img_upload_cache ', this.files)//Update store file cache}, Empty picture Empty () {this.files.splice (0, This.files.length) this. $store. Commit (' Set_img_upload_cache ', this.fi Les)//Update store file cache this. $store. Commit (' set_img_paths ', []}}}, Beforecreate () {this. $store. Commit (' set_img_s Tatus ', ' ready ')//update file upload status}, 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 ' )//update file upload status}}}}</script><style lang= "less" scoped>...</style>
The above code has some comments ordinal, is the main idea of this plug-in design, the other code is easier to understand, respectively
- ① after selecting the file, the
img_status
status becomes selected
.
- ② converts the uploaded image file to the Base64 format for thumbnail display.
- ③ creates a form object that stores the files to be uploaded.
- ④ Note the
name
attribute value here, temporarily write to die, the design is intended to specify properties from the component name
, if it is multi-file, the name
array ordinal of the property increments from 0.
- ⑤ does not rely on any AJAX request plug-ins to
XMLHttpRequest
create requests using native objects.
- ⑥ stores the upload path returned by the server after the upload is successful.
- ⑦ detects the upload status and performs an upload operation when the status is set to when the plugin is used
img_status
uploading
.
Use
Refer to GitHub and NPM for this project.
Attention
When using this plug-in, you need the data format returned with the backend conventions as follows:
[{"error":0,"url":"\/uploads\/api\/201711\/25\/fde412bd83d3ec5d6a49769bd0c143cd.jpg"},{"error":0,"url":"\/uploads\/api\/201711\/25\/c6fd51f0388c63a0b6d350331c945fb1.jpg"}]
The preview is as follows:
Returns an array of uploaded paths, including the error
url
fields, each file has its own upload status, when it is 0, the upload is error
successful, and the uploaded path is returned.url
Improved
Subsequent releases intend to make the following improvements
- Pass the property name of the form
name
through the component.
- Customize the data format of the server response after successful upload, such as the custom
error
name and the state its value represents.
- Support for uploading other types of files, you can make your own upload file types in the component, and how to preview them.
Vue's mobile multi-image upload plugin Vue-easy-uploader