在開發過程中遇到了這種情況, 當在新建某個內容時 (彈框展示 ),圖片上傳過程中 若是關閉的彈框 圖片仍然在上傳 可能導致一些錯誤的發生
兩種解決方案:
1 圖片上傳完成之前講關閉或提交或取消的按鈕都置為不可用的狀態 ,這樣就避免了上面情況的發生;
2 關閉彈框時取消圖片的上傳
這里需要引入axios 的 source 的token
<template>
<div class="app-container">
<div class="search-container">
<el-button type="primary" plain @click="handleNew()">新建</el-button>
</div>
<el-dialog
title="新建"
:close-on-click-modal="!dialogVisible"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose"
>
<el-form ref="newFormModel" :model="newObj" :rules="rules">
<el-form-item class="my-el-form-item" prop="img" label="logo">
<el-upload
ref="fileupload"
class="avatar-uploader"
action
:limit="1"
:disabled="uploadLoading"
:show-file-list="false"
:http-request="getFile"
:on-success="handleAvatarSuccess"
accept=".png, .jpg"
>
<img v-if="newObj.img&&newObj.img.length>0" :src="newObj.img" class="avatar" />
<el-button
:class="newObj.img?'buttonIconC':''"
:disabled="uploadLoading"
size="small"
type="primary"
>點擊上傳</el-button>
</el-upload>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<!-- 方案一的解決方案 下面相關source 的內容刪掉既可-->
<!-- <el-button :disabled="uploadLoading" @click="handleClose()">取 消</el-button>
<el-button type="primary" :disabled="uploadLoading" @click="newSubmit()">確 定</el-button>-->
<!-- 方案二 -->
<el-button @click="handleClose()">取 消</el-button>
<el-button type="primary" @click="newSubmit()">確 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { uplaodImageApi } from '@/api/apiFile'
export default {
data() {
return {
CancelToken: null,
source: null,
dialogVisible: false,
uploadLoading: false,
rules: {
img: [
{ required: true, message: '請選擇需要上傳的ogo', trigger: 'change' }
]
},
newObj: {
img: ''
}
}
},
watch: {
// 監控當 上傳文件過程中突然關閉彈框 取消文件的上傳 uploadLoading表示是否在上傳中
dialogVisible: function(newVal, oldVal) {
if (newVal === false && oldVal === true && this.uploadLoading) {
// 取消請求(message 參數是可選的)
this.source.cancel('Image upload cancelled.')
// 取消上傳之后做一些初始化工作
this.resetForm()
}
}
},
beforeMount() {
this.CancelToken = this.axios.CancelToken
this.source = this.CancelToken.source()
},
methods: {
handleNew() {
this.dialogVisible = true
},
resetForm() {},
handleClose() {
this.dialogVisible = false
},
newSubmit() {},
uplaodImageFile(img) {
const _self = this
const formData = new FormData()
formData.append('file', img)
this.source = this.CancelToken.source()
uplaodImageApi(formData, this.source.token)
.then(response => {
this.$message({
message: 'Upload success',
type: 'success'
})
this.newObj.img = response.data.url
//上傳成功之后 清空表單驗證中的部分img內容
this.$refs['newFormModel'].clearValidate('img')
setTimeout(function() {
_self.handleAvatarSuccess()
}, 2000)
})
.catch(msg => {
if (this.axios.isCancel(msg)) {
// 注意:在此處清空source 因為 不清空會使下次的請求 會被默認取消
this.source = {}
console.log('Request canceled', msg)
} else {
this.$message({
message: msg || 'Upload Error',
type: 'error'
})
this.handleAvatarSuccess()
}
})
},
getFile(value) {
this.uploadLoading = true
const img = value.file
if (this.beforeAvatarUpload(img)) {
this.uplaodImageFile(img)
} else {
this.handleAvatarSuccess()
}
},
handleAvatarSuccess(res, file) {
this.uploadLoading = false
this.$refs['newFormModel'].validateField('img')
this.$refs.fileupload.clearFiles()
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg'
const isPNG = file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG && !isPNG) {
this.$message.error('上傳頭像圖片只能是 JPG或PNG 格式!')
}
if (!isLt2M) {
this.$message.error('上傳頭像圖片大小不能超過 2MB!')
}
return isLt2M && (isJPG || isPNG)
}
}
}
</script>
注意: 在過程中可以會報錯 Cannot read property 'source' of undefined
上面錯誤原因在於 引入axios方式不對 ,上面的source 也可能是protool 或者 CancelToken都是因為 在注入axios時方式不對
axios 並不是 vue的插件 而是一個基於 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中;所以使用時不能使用 Vue.use(axios),如此使用會報上面的錯誤;
需要將axios 綁定到 vue實例的原型上面
import axios from 'axios' Vue.prototype.axios = axios
參考文檔:
http://www.axios-js.com/zh-cn/docs/
https://github.com/axios/axios
