最近需要把上傳的圖片信息存儲(chǔ)到數(shù)據(jù)庫(kù),以base64的方式,需要重新封裝一下antd的upload組件
1. 使用方法
引入組件然后配置一下即可使用,配置項(xiàng)包括
- defaultImageList,需要回顯的圖片(必傳)把鉴,[ url1, url2 ]
- fileTypeList ,文件格式(可選)儿咱,默認(rèn)不做限制
- limitSize 庭砍,單個(gè)圖片大小限制(可選),單位MB
- limitNum 混埠,上傳圖片個(gè)數(shù)限制(可選)怠缸,默認(rèn)200個(gè)
- multiple ,是否可以多選(可選)钳宪,默認(rèn)否
- disabled 揭北,是否禁用(可選),默認(rèn)否
- 引用組件
<template>
<div>
<b-upload-image-base64 ref="bUploadImageBase64" :limitNum="1" @change="change" :defaultImageList="data" />
</div>
</template>
<script>
import bUploadImageBase64 from '@/components/BUploadImageBase64'
export default {
components: {
bUploadImageBase64
},
data() {
return {
data: ['https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'],
defaultImageList: []
};
},
methods: {
change(e) {
console.log('e', e)
}
},
};
</script>
<style>
</style>
- 組件
<template>
<div class="clearfix">
<a-upload
:beforeUpload="beforeImageUpload"
list-type="picture-card"
:file-list="imageList"
:multiple="multiple"
:disabled="disabled"
@change="handleImageChange"
@preview="handlePreview"
:custom-request="customRequest"
>
<div v-if="imageList.length < limitNum && !disabled">
<a-icon type="plus"/>
<div class="ant-upload-text">上傳</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>
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)
})
}
export default {
props: {
defaultImageList: {
type: Array,
default: function() {
return []
},
required: true
},
fileTypeList: {
type: Array,
default: function() {
return []
},
required: false
},
limitSize: {
type: Number,
default: 5,
required: false
},
limitNum: {
type: Number,
default: 20,
required: false
},
multiple: {
type: Boolean,
default: false,
required: false
},
disabled: {
type: Boolean,
default: false,
required: false
}
},
data() {
return {
previewVisible: false,
previewImage: '',
imageList: []
}
},
watch: {
defaultImageList(newVal) {
this.imageList = this.handleData(newVal)
}
},
created() {
this.imageList = this.handleData(this.defaultImageList)
},
methods: {
// ---------------------------------------------img--start
beforeImageUpload(file) {
return new Promise((resolve, reject) => {
if (!this.fileTypeList) {
const index = this.fileTypeList.indexOf(file.type)
if (index > 0) {
this.$message.error(`您只能上傳${this.fileTypeList[index]}文件`)
}
}
const limitSize = file.size / 1024 / 1024 < this.limitSize
if (!limitSize) {
this.$message.error(`文件大小不能大于${this.limitSize}MB`)
return reject(new Error(`文件大小不能大于${this.limitSize}MB`))
}
return resolve(true)
})
},
async handlePreview(file) {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj)
}
this.previewImage = file.url || file.preview
this.previewVisible = true
},
handleCancel() {
this.previewVisible = false
},
customRequest({ action, file, onSuccess, onError, onProgress }) {
new Promise(resolve => {
const fileReader = new FileReader()
fileReader.readAsDataURL(file)
fileReader.onload = () => {
let index = {
uid: this.genId(5),
name: file.name,
status: 'done',
url: fileReader.result
}
this.imageList = [...this.imageList.filter(item => item.status === 'done'), index]
this.$message.success('文件上傳成功吏颖!')
this.handleChange()
resolve(fileReader.result)
}
})
},
handleImageChange(info) {
let fileList = [...info.fileList]
this.imageList = fileList
this.handleChange()
},
handleChange() {
let index = this.imageList.filter(item => item.url).map(item => {
return item.url
})
this.$emit('change', index ? index : [])
},
genId(length) {
return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36)
},
handleData (list) {
return list.map(item => {
let index = this.genId(5)
return {
uid: index,
name: index,
status: 'done',
url: item
}
})
}
// ---------------------------------------------img--end
}
}
</script>
<style>
/* 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>
2. 封裝遇到的坑
因?yàn)槭亲约簩?shí)現(xiàn)上傳邏輯需要使用屬性:custom-request="customRequest"
組件的運(yùn)行順序是beforeImageUpload
->customRequest
- 一開(kāi)始的校驗(yàn)需要寫(xiě)在beforeImageUpload中搔体,主要是驗(yàn)證文件格式,文件大小
- 然后進(jìn)入自定義的上傳邏輯半醉,這里主要是讀取圖片為base64疚俱,然后放入回顯的數(shù)組中,這樣組件就可以顯示上傳的圖片了缩多,此時(shí)還需要回調(diào)base64
- handleChange方法主要是刪除圖片使用呆奕,需要過(guò)濾出非undefined的,剩余的圖片并回傳base64