Vue中图片上传组件封装-antd的a-upload二次封装的实例
作者:JackieDYH
这篇文章主要介绍了Vue中图片上传组件封装-antd的a-upload二次封装的实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
图片上传组件封装-antd的a-upload二次封装
api
const publicApi = { UploadImage: '/common/uploadImage', DeleteImage: '/common/deleteImage', } /** * 上传图片 * @param {*} parameter * @returns */ export function UploadImage(parameter) { return request({ url: publicApi.UploadImage, method: 'post', data: parameter }) } /** * 删除图片 :name * @param {*} parameter * @returns */ export function DeleteImage(parameter) { return request({ url: `${publicApi.DeleteImage}/${parameter}`, method: 'delete' // params: parameter }) }
组件封装
<template> <div class="upbase"> <!-- 进度条--> <div v-show="progressVisible" class="progress-container"> <div class="progress-bar"></div> </div> <a-upload v-if="!uploadType" :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-upload v-else name="file" :file-list="imageList" :beforeUpload="beforeImageUpload" :multiple="multiple" :disabled="disabled" :custom-request="customRequest" @change="handleImageChange" > <!-- list-type="picture" --> <div v-if="imageList.length < limitNum && !disabled"> <a-button> <a-icon type="upload" /> 上传 </a-button> </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 { UploadImage, DeleteImage } from '@/api/public' 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) }) } function getName(url) { const list = url.split('/') return list[list.length - 1].split('.')[0] } export default { name: 'UpBase64', props: { defaultImageList: { type: Array, default: function () { return [] }, required: true, }, // 组件展示样式 uploadType: { type: Boolean, default: false, required: false, }, // 文件类型列表 fileTypeList: { type: Array, default: function () { return [] }, required: false, }, // 容量大小 limitSize: { type: Number, default: 2, required: false, }, // 个数 limitNum: { type: Number, default: 20, required: false, }, // 是否支持多选 multiple: { type: Boolean, default: false, required: false, }, // 是否禁用 disabled: { type: Boolean, default: false, required: false, }, dwidth: { type: Number, default: 0, require: false, }, dheight: { type: Number, default: 0, require: false, }, }, data() { return { previewVisible: false, progressVisible: false, progressValue: 10, 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.length != 0) { const index = this.fileTypeList.indexOf(file.type) if (index <= -1) { this.$message.error(`您只能上传${this.fileTypeList}文件`) return reject(new Error(`您只能上传${this.fileTypeList}文件,不能传${file.type}文件`)) } } const limitSize = file.size / 1024 / 1024 < this.limitSize if (!limitSize) { this.$message.error(`文件大小不能大于${this.limitSize}MB`) return reject(new Error(`文件大小不能大于${this.limitSize}MB`)) } const checkSize = this.checkImageWH(file, this.dwidth, this.dheight) return Promise.resolve(checkSize) .then(() => resolve()) .catch((e) => { reject(e) }) }) }, checkImageWH(file, width, height) { // 参数分别是上传的file,想要限制的宽,想要限制的高 const that = this return new Promise(function (resolve, reject) { let filereader = new FileReader() filereader.onload = (e) => { let src = e.target.result const image = new Image() image.onload = function () { if ((width && this.width !== width) || (height && this.height !== height)) { // 上传图片的宽高与传递过来的限制宽高作比较,超过限制则调用失败回调 const message = `图片宽高不满足,需要:宽 ${width || '不限制'},高 ${height || '不限制'}\n,当前图片宽:${ this.width },高:${this.height}` that.$message.error(message) reject(new Error(message)) } else { resolve({ width: this.width, height: this.height }) } } image.onerror = reject image.src = src } filereader.readAsDataURL(file) }) }, 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 }) { this.progressVisible = true new Promise((resolve) => { const fileReader = new FileReader() // 转化为base64 fileReader.readAsDataURL(file) fileReader.onload = async () => { let index = { uid: this.genId(5), name: file.name, status: 'done', url: fileReader.result, } let params = { name: index.uid, data: index.url, } try { let res = await UploadImage(params) index.url = res.result.url if (res.status == 1) { setTimeout(() => { this.imageList = [...this.imageList.filter((item) => item.status === 'done'), index] this.$message.success('文件上传成功!') this.progressVisible = false this.handleChange() resolve(fileReader.result) }, 2000) } else { this.imageList = [...this.imageList.filter((item) => item.status === 'done')] this.$message.success(res.msg) this.handleChange() resolve(fileReader.result) } } catch (error) { console.log('upimg:', error) } finally { } } }) }, // 处理事件 async handleImageChange(info) { try { // 删除图片 let res = await DeleteImage(getName(info.file.url)) console.log(res, 89) if (res.status == 1) { this.$message.success('删除成功!') } else { this.$message.error('删除失败!') } } catch (error) { // console.log('delimg:', error) } finally { let fileList = [...info.fileList] this.imageList = fileList this.handleChange() } }, handleChange() { let index = this.imageList .filter((item) => item.url) .map((item) => { return item.url }) // if (index?.length <= 0) return 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 lang="less" scoped> .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> <style> .progress-container { width: 100px; height: 7px; background-color: #ffffff; border-radius: 5px; } .progress-bar { height: 100%; border-radius: 5px; animation-fill-mode: forwards; animation-name: progressBar; animation-iteration-count: infinite; background-color: #44cef6; animation-duration: 2s; animation-iteration-count: 1; } @keyframes progressBar { 0% { width: 0%; } 100% { width: 100%; } } </style>
使用
<template> <page-header-wrapper> <div class="khdztps"> <div class="container"> <div class="left"> <div class="wrap"> <div class="title"> <h2>客户端底图上传</h2> </div> <span class="tips">*上传格式为“.jpg 和.png“,大小不得超过1M,(375*665)</span> <b-upload-image-base64 ref="bUploadImageBase641" :limitNum="1" @change="imageChange($event, 'inviteBgImageList')" :defaultImageList="inviteBgImageList" :dwidth="375" :dheight="665" /> </div> <div class="wrap"> <div class="title"> <h2>客户端ICON替换</h2> </div> <span class="tips">*上传格式只能为“.png”,大小不得超过300k,(24*24)x3</span> <div class="icon"> <div class="wxz"> <span class="title">未选中</span> <div class="imgBox"> <b-upload-image-base64 ref="bUploadImageBase642" :limitNum="1" @change="imageChange($event, 'inviteHomeImageList')" :defaultImageList="inviteHomeImageList" :dwidth="24 * 3" :dheight="24 * 3" /> </div> </div> </div> </div> </div> </div> <a-button type="primary" @click="saveSubmit">保存并预览</a-button> </div> </page-header-wrapper> </template> <script> import { commitCustomConfigure, queryCustomConfigure } from '@/api/feedback' import bUploadImageBase64 from '@/components/Plug/BUploadImageBase64.vue' export default { name: 'Khdztps', components: { bUploadImageBase64, }, data() { return { inviteBgImageList: [], inviteHomeImageList: [], dataList: { BGUrl: '', HomeUrl: '', }, } }, created() {}, mounted() { this.queryCustomConfigure() }, methods: { saveSubmit() { this.commitCustomConfigure() }, // 保存 async commitCustomConfigure() { try { let res = await commitCustomConfigure(this.dataList) console.log(res, 89) if (res.status == 1) { this.$message.success('设置成功!') } else { this.$message.error(res.msg) } } catch (error) { console.log('sub:', error) } }, // 获取 - 数据回填 async queryCustomConfigure() { try { let res = await queryCustomConfigure() console.log(res, 89) if (res.status == 1) { // this.$message.success('成功!') this.dataList = res.result if (res.result.BGUrl) { this.inviteBgImageList.push(res.result.BGUrl) } if (res.result.HomeUrl) { this.inviteHomeImageList.push(res.result.HomeUrl) } } else { this.$message.error(res.msg) } } catch (error) { console.log('sub:', error) } }, // 图片上传成功赋值 imageChange(e, key) { console.log(e, key) switch (key) { // 图片 case 'inviteBgImageList': this.dataList.BGUrl = e[0] || '' break case 'inviteHomeImageList': this.dataList.Unselect.Home = e[0] || '' break default: break } }, }, destroyed() {}, activated() {}, deactivated() {}, } </script>
优化
原本 :defaultImageList="inviteBgImageList" ==>['图片链接']
现在 :defaultImageList="Array(form.BGUrl)" ==>['图片链接']
原本的写法需要提前定义好一个空数组,才能将数据回填显示出图片
现在的写法是直接使用form中的字符串转换成一个数组回填显示图片
二者方式均可使用,看使用方式
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。