Vue 初心者筆記 #38 後台上傳商品檔案的功能

本篇筆記介紹產品 Modal 裡的圖片檔案上傳功能該如何製作。

串接檔案上傳 API

STEP 1:監聽檔案上傳

  • 加入事件監聽器 (v-on) 監聽檔案上傳:@change="uploadFile"

透過 @change 事件來監聽上傳的檔案是否有變更,如果檔案變更了,就會觸發 uploadFile 這個方法。

1
2
3
4
5
6
7
<input
type="file"
id="customFile"
class="form-control"
ref="files"
@change="uploadFile"
/>

STEP 2:取得上傳的檔案

  • 取得圖檔:const uploadFile = this.$refs.files.files[0]

uploadFile 方法中,我們可以先透過 console.log(this) 查看上傳的檔案有哪些資料格式。
仔細尋找後,可以發現我們想要的圖檔就放在 $refsfilesfiles[0] 這個地方,我們就把這個檔案取出來使用。

refs

STEP 3:建立 FormData 物件

  • 建立 FormData 物件:const formData = new FormData()
  • 新增 key/value 欄位:formData.append("file-to-upload", uploadFile)

由於這裡的後端規則是用 FormData 傳,所以我們也要使用 FormData 的格式。

FormData() - Web APIs | MDN

STEP 4:送出圖檔

  • 定義 API 路徑
  • 將格式改成 FormData 的格式

這裡要把格式改為 FormData,所以 post 後方必須多加一個物件,來把表單的 enctype 屬性改為 multipart/form-data

我們在表單中設置了 enctype 屬性,也就是指定了 Request Headers 中 Content-type 的值

STEP 5:圖片路徑的雙向綁定

可以取得加上授權的圖片路徑後,我們還想要把這個路徑對應到 tempProductimageUrl 裡面,讓畫面上即時出現剛才上傳上去的檔案。

然而,如果直接把 response.data.imageUrl 指定給表單用的 vm.tempProduct.imageUrl 是行不通的,因為這樣子沒有達到”雙向綁定”。

為何無法雙向綁定呢?
主要是因為一開始在 data 中沒有預定義 imgUrl 屬性,這個屬性需要等到上傳圖片,並取得圖片的雲端網址之後才會出現。
也就是說 imgUrl 沒有 gettersetter,所以我們這邊必須使用 $set 來強制加入雙向綁定。

在使用 Vue 綁定資料的時候,如果一開始寫入資料的時候沒有預先定義某個資料的話,該資料便不會跟著動態更新,並且會出現錯誤(不會出現 getter 與 setter),而這個資料也無法即時地反應在畫面上。

1
vm.$set(vm.tempProduct, 'imageUrl', response.data.imageUrl);

完成後,我們上傳圖片時,表格中”圖片網址”的欄位就會自動帶上 tempProduct.imageUrl 呈現圖片網址了。
下方也可以使用 tempProduct.imageUrl 來顯示剛才上傳的圖片,可以作為預覽圖。

1
<img class="img-fluid" :src="tempProduct.imageUrl" alt />

整體畫面如下圖所示:

examplePicture

關於雙向綁定可參考之前的筆記:Vue.js 初心者筆記:使用 vm.$set 動態添加新屬性

上傳檔案範例程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
methods: {
// 上傳檔案
uploadFile() {
const uploadFile = this.$refs.files.files[0];
const formData = new FormData();
formData.append("file-to-upload", uploadFile);
const vm = this;
const url = `${process.env.APIPATH}/api/${process.env.CUSTOMPATH}/admin/upload`;
this.$http.post(url, formData, {
// 將格式改成 formData 的格式
headers: {
"content-Type": "multipart/form-data"
}
})
.then(response => {
console.log(response.data); // 可取得加上授權的圖片路徑
// 對應到 tempProduct 的 imageUrl 裡面
if (response.data.success) {
vm.$set(vm.tempProduct, "imageUrl", response.data.imageUrl); // 雙向綁定
}
});
}
},

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。