1. 程式人生 > 實用技巧 >vue+element實現圖片非同步上傳

vue+element實現圖片非同步上傳

現有如下需求

  1、使用者可以選擇多張圖片,點選按鈕完成上傳

  2、向後臺傳送的資料必須為base64位編碼的格式

  3、圖片名以下標命名

  4、介面只支援單張圖片的上傳,上傳成功後返回一個線上的圖片地址

  5、最終拿到一個長度為選擇的圖片的數量,內容是每張圖片返回的線上圖片地址的一個數組

實現思路

  1、選中圖片後即時的將選擇的圖片轉換為base64存入一個數組中,刪除該圖片時也在陣列中將該圖片刪除,始終保證存放base64的陣列和已選擇的圖片相對應

  2、點選上傳按鈕利用 for of 遍歷 base64 陣列,在每一遍的迴圈中請求上傳圖片的介面,傳遞當前圖片的base64編碼和當前迴圈的下標

  3、等待介面返回結果,將返回的結果存入一個數組中,在進行下一次迴圈

  4、迴圈完畢後拿到存放結果的陣列

從思路上上看我們需要重點關注的就是如何處理呼叫介面返回結果後再進行下一次迴圈,並如何在迴圈外邊拿到返回的陣列

開始擼碼

<template>
  <div class="about">
    <!-- 
       action:必填,圖片上傳地址,我們為非同步上傳因此此處用井號代替
       on-preview:點選檔案列表中已上傳的檔案時的鉤子
       on-remove:檔案列表移除檔案時的鉤子
       auto-upload:是否在選取檔案後立即進行上傳
       multiple:是否支援多選檔案
       limit:最大允許上傳個數
       on
-change:檔案狀態改變時的鉤子,新增檔案、上傳成功和上傳失敗時都會被呼叫 on-exceed:檔案超出個數限制時的鉤子 accept:接受上傳的檔案型別(thumbnail-mode 模式下此引數無效) --> <el-upload action="#" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :auto-upload="false" :multiple
="true" :limit="5" :on-change="changeIamge" :on-exceed="onExceed" accept="image/*" > <i class="el-icon-plus"></i> {{base64ImageData.length}}/5 </el-upload> <el-dialog :visible.sync="dialogVisible"> <img width="100%" :src="dialogImageUrl" alt /> </el-dialog> <el-button type="primary" @click="uploadImg"> 點選上傳 <i class="el-icon-upload el-icon--right"></i> </el-button> <span>{{message}}</span> </div> </template> <script> import http from "../util/http"; export default { data() { return { // 彈出圖片大圖路徑 dialogImageUrl: "", dialogVisible: false, // 存放base64位編碼的圖片集合 base64ImageData: [], message: "當前圖片尚未上傳", }; }, methods: { // 刪除圖片觸發 handleRemove(file, fileList) { // 刪除存放base64位編碼的圖片集合 let removeIndex = this.base64ImageData.findIndex( (item) => file.uid === item.uid ); // 利用findIndex獲取當前刪除的圖片下標 this.base64ImageData.splice(removeIndex, 1); }, // 檢視圖片大圖 handlePictureCardPreview(file) { this.dialogImageUrl = file.url; this.dialogVisible = true; }, // 超出最大上傳數量觸發 onExceed() { this.$alert("超出最大上傳數量"); }, // 選擇圖片時觸發 changeIamge(file, fileList) { // 此處呼叫是選擇圖片就立即轉換為base64 this.getBase64(file.raw).then((res) => { this.base64ImageData.push({ base64Code: res, uid: file.uid, }); }); }, // 將選擇的圖片處理成為Base64 getBase64(file) { // 返回Promise格式 return new Promise((resolve, reject) => { let reader = new FileReader(); let imgResult = ""; reader.readAsDataURL(file); reader.onload = () => { imgResult = reader.result; }; // 成功返回 reader.onloadend = () => { resolve(imgResult); }; // 失敗返回 reader.onerror = () => { reject(error); }; }); }, // 點選上傳按鈕 async uploadImg() { // 陣列非空校驗 if (this.base64ImageData.length === 0) { this.$alert("請選擇圖片再進行上傳操作"); return; } // 存放線上的圖片路徑集合 let resultImage = []; // 利用for of 遍歷依次上傳圖片 entries()可以解決for of 遍歷獲取不到下標的問題 for (const [index, item] of this.base64ImageData.entries()) { let data = { imgName: `圖片_0${index + 1}`, baseCode: item.base64Code, fileName: "jpg", }; // axync await 等待當前迴圈圖片上傳完成在進行下一張圖片的上傳 let resImage = await this.uploadPostFun(data); // 此狀態嗎和後臺商定,成功會返回六個零 if (resImage.code === "000000") { resultImage.push(resImage.result.imgUrl); this.message = `${index + 1}張圖片上傳成功`; } else { this.message = `${index + 1}張圖片上傳失敗`; } } // 在迴圈外側拿到返回的圖片路徑 console.log(resultImage); }, // 上傳方法,方法成功會返回一個線上的URl圖片路徑 uploadPostFun(data) { return http.post("/fileupload/image", data); }, }, }; </script>