1.需求背景:
最近在做一個(gè)IM即時(shí)通訊系統(tǒng)的開發(fā)工作,其中有一項(xiàng)需求是:在第三方截圖軟件(如QQ、微信、釘釘)截圖后,能在聊天輸入框中粘貼該圖片,支持預(yù)覽,點(diǎn)擊發(fā)送后能夠上傳。
由于IM的特殊性,不同于常規(guī)的B端項(xiàng)目,其對(duì)用戶體驗(yàn)的要求極高,高頻的交互操作,不允許百毫秒或以上級(jí)別的延遲。
嘗試過(guò)采用github上的一些富文本編輯框插件,無(wú)法完全滿足需求,存在一些缺陷,踩了一些坑。所以打算采用最原生,最穩(wěn)定的方案,類似網(wǎng)頁(yè)版微信。
2.操作流程:
用戶使用第三方軟件截圖? ? --》在輸入框中粘貼? ? --》彈框顯示圖片預(yù)覽? ? --》點(diǎn)擊發(fā)送,http請(qǐng)求,同時(shí)展示臨時(shí)消息模板? ? --》待響應(yīng)拿到網(wǎng)絡(luò)url,用其替換臨時(shí)消息
3.具體方案:
前三步可以看做一個(gè)整體,要做的事情也不多:監(jiān)聽輸入框的onPaste事件,使用FileReader對(duì)象讀取圖片為base64格式并展示在預(yù)覽框中,如下

這里創(chuàng)建了一個(gè)FileReader構(gòu)造函數(shù),其為HTML5新特性之一。代碼中將其讀取成了DataURL格式,讀取過(guò)程為異步事件,使用onload作為讀取監(jiān)聽回調(diào),并通過(guò)參數(shù)e.target.result獲取圖片的base64格式,渲染到img標(biāo)簽的src屬性中來(lái)獲取圖片預(yù)覽。除此格式之外,還提供了多種格式的讀?。?/p>

其中三個(gè)是用來(lái)讀取文件,另一個(gè)是用來(lái)中斷讀取的,功能如下:
readAsText:該方法有兩個(gè)參數(shù),其中第二個(gè)參數(shù)是文本的編碼方式,默認(rèn)值為 UTF-8。這個(gè)方法非常容易理解,將文件以文本方式讀取,讀取的結(jié)果即是這個(gè)文本文件中的內(nèi)容。?
readAsBinaryString:該方法將文件讀取為二進(jìn)制字符串,通常我們將它傳送到后端,后端可以通過(guò)這段字符串存儲(chǔ)文件。?
readAsDataURL:這是例子程序中用到的方法,該方法將文件讀取為一段以 data: 開頭的字符串,這段字符串的實(shí)質(zhì)就是 Data URL,Data URL是一種將小文件直接嵌入文檔的方案。這里的小文件通常是指圖像與 html 等格式的文件。
需要注意的是,無(wú)論讀取成功或是失敗,方法并不會(huì)返回讀取結(jié)果,這一結(jié)果(儲(chǔ)存在result屬性中)要用FileReader處理事件去獲取:

讀取file對(duì)象的同時(shí),需要將其存儲(chǔ)在state中,在用戶點(diǎn)擊發(fā)送時(shí)使用:

由于每個(gè)用戶的工作環(huán)境,網(wǎng)速不能確定,考慮到圖片上傳可能占用一些時(shí)間,如此時(shí)不顯示圖片,會(huì)讓用戶造成誤解,影響用戶體驗(yàn),所以加入了臨時(shí)消息列表功能,流程如下:
用戶點(diǎn)擊發(fā)送按鈕? ? --》消息列表先展示base64圖片,同時(shí)發(fā)送http請(qǐng)求傳遞file對(duì)象? ? --》等待服務(wù)器返回網(wǎng)絡(luò)url? ? --》刪除相應(yīng)臨時(shí)消息,展示真實(shí)圖片
這里使用時(shí)間戳作為臨時(shí)消息ID,以確保臨時(shí)消息的對(duì)應(yīng)關(guān)系,并保證唯一性。
使用原生XHR傳遞并監(jiān)聽ajax請(qǐng)求。
圖片渲染完成后消息列表滾動(dòng)條自動(dòng)滾動(dòng)到列表底部。
創(chuàng)建同為HTML5新特性的FormData對(duì)象,并使用append方法為對(duì)象添加file項(xiàng),然后發(fā)送。成功拿到網(wǎng)絡(luò)url后,刪除相應(yīng)臨時(shí)消息并展示真實(shí)消息。
最后一點(diǎn),也是前端工程師必須注意和解決的一點(diǎn):API兼容性。
本方案,兼容性最大的API瓶頸是paste方法,請(qǐng)使用者注意。can I use查詢?nèi)缦拢?/p>

完結(jié)撒花