用 Vue.js + Firebase 製作即時聊天功能(2) - storage

繼上次的練習用 Vue.js + Firebase 製作即時聊天功能
這次用firebase的storage來擴充傳圖片的功能!

>DEMO<

>原始碼-GitHub<

Firebase設定

要先到左側選單找到storage,
進去啟用後再回到首頁複製一次連結資訊。

要確定storage中已經有值喔!

流程

  1. 點選傳送圖片
  2. 選取圖片/使用拍照功能
  3. 上傳到storage並顯示進度條
  4. 完成將帶回的圖片連結寫進db
  5. 透過realtime db更新,讓所有連線者即時看到圖片

刻畫面

加個小按鈕,並且把圖片顯示框寫好,
紀錄一下遇到的問題:
當把input file隱藏起來後,一直無法套上pointer的效果,
結果爬文後才發現要讓他有pointer的效果要加上padding-left:100%

1
2
3
4
5
6
7
8
9
10
11
.roomBottom__tools_upload input {
width: 100%;
height: 100%;
left: 0;
right: 0;
opacity: 0;
position: absolute;
cursor: pointer;
/* 讓input file可以支援pointer要加pl100% */
padding-left: 100%;
}

主程式

僅列出更新的部分,其他同上一篇,
一樣不包含落落長的CSS,完整參考github

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- ...略... -->
<!-- 區塊:body 中的content(other&self都更新了) -->
<div class="messageBox__content">
<!-- 新增v-if判斷格式,依據不同的格式顯示不同樣式與內容 -->
<div v-if="item.type == 'text'" class="messageBox__message">{{item.message}}</div>
<div v-if="item.type == 'image'" class="messageBox__image"><img :src="item.message"></div>
</div>
<!-- 新區塊:上傳進度條 -->
<!-- 使用v-show,當符合條件時才顯示(upload==ture) -->
<div v-show="upload" class="messageBox messageBox--self">
<div class="messageBox__progress">
<div id="js-progressBar" class="messageBox__progress--state"></div>
<div class="messageBox__progress--number">{{progress}}</div>
</div>
</div>
<!-- 區塊:bottom -->
<div class="roomBottom__tools">
<div class="roomBottom__tools_upload">
<!-- 使用accept="image/*"讓手持裝置可選圖片來源(拍照/相本) -->
<!-- 加入onchange事件:@change="sendImage($event)" -->
<input type="file" accept="image/*" @change="sendImage($event)">
<img src="../assets/tools_file.png">
</div>
</div>
<!-- ...略... -->
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// 跟msgRef一樣先宣告好storage會用到的資料夾
const storageRef = firebase.storage().ref('/images/');

data() {
return {
// ..略
upload: false, // 用來判斷是否顯示進度條
progress: '' // 用來放進度條%數文字用
}
},
methods: {
/** 傳送訊息 */
sendMessage(e) {
// ..略
msgRef.push({
userName: userName.value,
type: 'text', // 新增狀態,傳文字訊息是text
message: message.value,
timeStamp: vm.getTime()
})
},
/** 傳送圖片 */
sendImage(e) {
const vm = this;
const userName = document.querySelector('#js-userName');
// 取得上傳檔案的資料
const file = e.target.files[0];
const fileName = Math.floor(Date.now() / 1000) + `_${file.name}`;
const metadata = {
contentType: 'image/*'
};
// 取得HTML進度條元素
let progressBar = document.querySelector('#js-progressBar');
// 上傳資訊設定
const uploadTask = storageRef.child(fileName).put(file, metadata);
// 上傳狀態處理
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
/* 上傳進度 */
function(snapshot) {
let progress = Math.floor((snapshot.bytesTransferred / snapshot.totalBytes) * 100);
if(progress < 100) {
// 開啟進度條
vm.upload = true;
vm.progress = `${progress}%`;
progressBar.setAttribute('style',`width:${progress}%`);
}
},
/* 錯誤處理 */
function(error) {
msgRef.child('bug/').push({
userName: userName.value,
type: 'image',
message: error.code,
timeStamp: vm.getTime()
})
},
/* 上傳結束處理 */
function() {
var downloadURL = uploadTask.snapshot.downloadURL;
msgRef.push({
userName: userName.value,
type: 'image',
message: downloadURL,
timeStamp: vm.getTime()
})
// 關閉進度條
vm.upload = false;
});
}
}

有空的話再練習清單

  1. 加入拖曳傳圖功能
  2. 圖檔縮放框

心得

firebase的storage提供的API可以很輕鬆的取回上傳進度、以及上傳後的網址回傳,普遍常見的訊息儲存與圖片上傳都可以透過firebase來實現無後端程式。

今天一起來就開始邊寫邊測,功能實現真的好興奮啊XD

然後我這樣components越寫越長好像很糟糕,
我必須要趕快找正確拆分邏輯的作法了XD!