Vue中圖片上傳組件封裝-antd的a-upload二次封裝的實(shí)例
圖片上傳組件封裝-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"> <!-- 進(jìn)度條--> <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> <!-- 圖片預(yù)覽 --> <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, }, // 個(gè)數(shù) 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) { // 參數(shù)分別是上傳的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)) { // 上傳圖片的寬高與傳遞過來的限制寬高作比較,超過限制則調(diào)用失敗回調(diào) const message = `圖片寬高不滿足,需要:寬 ${width || '不限制'},高 ${height || '不限制'}\n,當(dāng)前圖片寬:${ 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() // 轉(zhuǎn)化為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">保存并預(yù)覽</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('設(shè)置成功!') } else { this.$message.error(res.msg) } } catch (error) { console.log('sub:', error) } }, // 獲取 - 數(shù)據(jù)回填 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>
優(yōu)化
原本 :defaultImageList="inviteBgImageList" ==>['圖片鏈接']
現(xiàn)在 :defaultImageList="Array(form.BGUrl)" ==>['圖片鏈接']
原本的寫法需要提前定義好一個(gè)空數(shù)組,才能將數(shù)據(jù)回填顯示出圖片
現(xiàn)在的寫法是直接使用form中的字符串轉(zhuǎn)換成一個(gè)數(shù)組回填顯示圖片
二者方式均可使用,看使用方式
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue制作點(diǎn)擊切換圖片效果的詳細(xì)思路與步驟
這篇文章主要給大家介紹了關(guān)于vue制作點(diǎn)擊切換圖片效果的詳細(xì)思路與步驟,圖片切換是一個(gè)很經(jīng)典的Vue入門學(xué)習(xí)案例,在你學(xué)習(xí)完一些基本的v-指令后,你可以嘗試去寫一個(gè)簡單的demo去鞏固和熟悉這些指令的使用方法,需要的朋友可以參考下2023-11-11Vue 級聯(lián)下拉框的設(shè)計(jì)與實(shí)現(xiàn)
在前端開發(fā)中,級聯(lián)選擇框是經(jīng)常用到的,這樣不僅可以增加用戶輸入的友好性,還能減少前后端交互的數(shù)據(jù)量。本文就介紹一下使用Vue實(shí)現(xiàn)級聯(lián)下拉框,感興趣的可以了解一下2021-07-07使用webpack搭建vue項(xiàng)目及注意事項(xiàng)
這篇文章主要介紹了使用webpack搭建vue項(xiàng)目的方法,本文以開發(fā)環(huán)境為例,通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06VueJs單頁應(yīng)用實(shí)現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例
本篇文章主要介紹了VueJs單頁應(yīng)用實(shí)現(xiàn)微信網(wǎng)頁授權(quán)及微信分享功能示例,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07Vue3中實(shí)現(xiàn)拖拽和縮放自定義看板 vue-grid-layout的方法
這篇文章主要介紹了Vue3中實(shí)現(xiàn)拖拽和縮放自定義看板 vue-grid-layout的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03