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>
内容版权声明:除非注明,否则皆为本站原创文章。