思路
- 在beforeUpload时用fileList的长度和限制个数进行比较。当个数超出限制时报错。
- 在handleChange中监听并移出超出的图片
效果

完整代码
<template>
<div class='clearfix'>
<a-upload
:action='ACTION'
:headers='HEADERS'
accept='image/*'
multiple
list-type='picture-card'
:file-list='fileList'
:before-upload='beforeUpload'
@preview='handlePreview'
@change='handleChange'
>
<div v-if='fileList.length < limit'>
<a-icon type='plus' />
<div class='ant-upload-text'>
Upload
</div>
</div>
</a-upload>
<a-modal :visible='previewVisible' :footer='null' @cancel='handleCancel'>
<img alt='example' style='width: 100%' :src='previewImage' />
</a-modal>
</div>
</template>
<script>
import storage from 'store'
import { ACCESS_TOKEN } from '@/store/mutation-types'
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result)
reader.onerror = error => reject(error)
})
}
const ACTION = process.env.VUE_APP_API_BASE_URL_UPLOAD
const HEADERS = {
[ACCESS_TOKEN]: storage.get(ACCESS_TOKEN)
}
export default {
props: {
// 上传个数
limit: {
type: Number,
default: 2
},
// 文件最大大小 单位mb
fileSize: {
type: Number,
default: 5
}
},
data() {
return {
loading: false, // 是否有图片正在上传中
ACTION,// 请求地址
HEADERS,// 请求头
previewVisible: false, // 是否显示预览
previewImage: '',// 预览图片base64地址
fileList: [] // 图片列表
}
},
methods: {
handleCancel() {
this.previewVisible = false
},
async handlePreview(file) {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj)
}
this.previewImage = file.url || file.preview
this.previewVisible = true
},
handleChange(info) {
const status = info.file.status
let fileList = info.fileList
if (status === 'uploading') {
this.loading = true
} else if (status === 'done') {
if (info.file.response.code !== 0) {
this.$notification.error({
message: '上传失败',
description: `${info.file.response.message}`
})
}
this.loading = false
} else if (status === 'error') {
this.$notification.error({
message: info.file.name + '上传失败',
description: `status code :${info.file.xhr.status}`
})
fileList = fileList.filter(file => file.uid !== info.file.uid)
} else if (status === 'beforeUploadReject') {
if (info.file.statusText) {
this.$notification.error({
message: info.file.statusText
})
}
}
fileList = fileList.filter(file => file.status !== 'error' && file.status !== 'beforeUploadReject')
this.fileList = fileList
},
beforeUpload(file, fileList) {
// fileList 只包含了当次上传的文件列表,不包含已上传的文件列表
// 所以长度要加上已上传的文件列表的长度
const isLimit = (this.fileList.length + fileList.length) > this.limit
const indexOfFile = fileList.findIndex(item => item.uid === file.uid) + this.fileList.length
if (isLimit && indexOfFile === this.limit) {
file.status = 'beforeUploadReject'
file.statusText = '最多上传' + this.limit + '张图片'
return false
}
if (isLimit && indexOfFile > this.limit) {
file.status = 'beforeUploadReject'
return false
}
const isJpgOrPng = file.type.startsWith('image/')
if (!isJpgOrPng) {
file.status = 'beforeUploadReject'
file.statusText = '请上传图片'
return false
}
const isLtmb = file.size / 1024 / 1024 < this.fileSize
if (!isLtmb) {
file.status = 'beforeUploadReject'
file.statusText = `图片不能大于${this.fileSize}mb`
return false
}
}
}
}
</script>
<style scoped lang='less'>
/* you can make up upload button and sample style by using stylesheets */
.ant-upload-select-picture-card i {
font-size: 32px;
color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
margin-top: 8px;
color: #666;
}
</style>