來源| OSCHINA 社區(qū)
作者 | 京東云開發(fā)者-京東物流 劉海鼎
背景
前端文件上傳本來是一個常規(guī)交互操作,沒什么特殊性可言,但是最近在做文件上傳,需要實現(xiàn)截圖粘貼上傳,去找了下有沒有什么好用的組件,網(wǎng)上提供的方法有,但是沒找完整的組件來支持 cv 上傳,經(jīng)過了解發(fā)現(xiàn)可以用剪貼板功能讓自己的 cv 實現(xiàn)文件上傳,于是自己就整合了目前幾種文件上傳的交互方式,碼了一個支持 cv 的 vue3 文件上傳組件(造個輪子)。
介紹
作為一個完整的組件內(nèi)容還是挺多的,這里主要介紹下上傳交互中一些主要功能,包括上傳的幾種交互方式, 上傳進度的獲取,上傳類型的限制,默認上傳請求和自定義上傳請求。 以下代碼都是非完整代碼,大家用于參考實現(xiàn)過程,可以通過以下代碼修改來完成自己想要的交互功能。
幾種交互
1,點擊選擇上傳
點擊選擇是最常見的上傳交互,之前原生上傳控件,樣式修改比較麻煩,為了修改上傳樣式,我們可以把該控件設置隱藏,用其他元素通過從 click 交互,來觸發(fā)該文件選擇控件。在選擇文件控件上綁定 onchange 事件,該控件在 change 后獲取到文件,然后調(diào)用上傳方法,實現(xiàn)如下:
2,拖動上傳
拖拽文件上傳,首先在頁面上建立一個拖放區(qū)域,在拖放區(qū)域上綁定拖放事件,監(jiān)聽拖放事件 drop 內(nèi)容中 datTransfer 中是包含 files, 如果存在 files,獲取 files 然后調(diào)用上傳附件方法。 拖放區(qū)域可以通過事件 dragover 來檢查拖放文件是否進入拖放區(qū)域來設置拖放區(qū)域懸浮樣式,通過 dragleave 來檢查離開拖放區(qū)取消懸浮樣式。 進行交互提示 實現(xiàn)如下:
3,復制上傳(復制檢測區(qū)域設置)+
復制上傳的交互步驟
?將文件保存到剪貼板:執(zhí)行鍵盤快捷鍵或者使用鼠標復制
?將鼠標移動到可粘貼區(qū): 判斷是否移動到可粘貼區(qū),來確定是否在執(zhí)行粘貼后上傳,否則整個頁面都會作為粘貼區(qū)
?執(zhí)行粘貼操作:執(zhí)行鍵盤粘貼快捷鍵(ctrl+v) 粘貼區(qū)綁定 paste 事件,在觸發(fā) paste 事件前將鼠標移到粘貼區(qū),復制會被檢查不在粘貼區(qū),阻止上傳操作,實現(xiàn)如下:
+
上傳模式
根據(jù)以上三種交互,大家可自由組合上傳形式,比如點擊和拖拽,拖拽和粘貼組合等等,我這邊目前按點擊,拖拽,粘貼疊加組合,設置為:
?點擊上傳,click
?拖拽上傳 drag(包括點擊上傳和拖拽上傳)
?粘貼上傳 paste (包括點擊,拖拽和復制上傳)
通過傳參 uploadeMode 設置 (click, drag, paste)
組件設置:
+ +
組件應用
點擊上傳
文件限制
文件限制包括是否多文件上傳限制 multiple, 上傳數(shù)量 limit 限制,上傳類型 accept 限制,這些設置參考了 element-plus 上傳組件,在其基礎上做了簡化。實現(xiàn)如下 multiple 和 accept 首先需要在點擊控件上綁定,以便于在點擊選擇上傳時就能夠過濾對應文件,拖拽上傳和粘貼上傳,無法通過 input [type=file] 組件控制需要在上傳方法中判斷過濾,(以粘貼上傳為例) 組件實現(xiàn)
+
上傳進度設置
獲取文件上傳進度,使用 ajax 中的 progress 事件監(jiān)聽機制,回傳數(shù)據(jù) loaded 進度,和 ttotal 進行計算,獲取到計算的百分比通過 process 插槽線上在界面上。 具體實現(xiàn)如下: 組件實現(xiàn) 文件限制后執(zhí)行組件上傳,默認情況下走內(nèi)置的上傳方法,如果做了自定義,上傳進度也需要自己實現(xiàn)(自己實現(xiàn)過程可以參考內(nèi)置方法中的實現(xiàn))
// 上傳方法調(diào)用 ajaxUpload({...props, file}) // 上傳方法實現(xiàn) ajaxUpload = (options) => { const xhr = new XMLHttpRequest() const action = option.action console.log(xhr, xhr.upload) if (xhr.upload) { // 建立progress監(jiān)聽 xhr.upload.addEventListener('progress', (evt:any) => { const progressEvt = evt progressEvt.percent = evt.total > 0 ? (evt.loaded / evt.total) * 100 : 0 // 回傳進度數(shù)據(jù) option.onProgress(progressEvt) }) } }
同樣文件上傳成功,異常等方法也可以通過監(jiān)聽 load 并且判斷 xhr.status 來實現(xiàn),
xhr.addEventListener('load', () => { if (xhr.status < 200 || xhr.status >= 300) { return option.onError(getError(action, option, xhr)) } option.onSuccess(getBody(xhr)) })組件使用 ?配置獲取進度數(shù)據(jù)回調(diào)函數(shù) onProgress ?配置接收回傳的進度數(shù)據(jù)進行賦值 ?配置進度條插槽顯示進度數(shù)據(jù)
自定義上傳請求 點擊上傳{{progressval}} %
默認情況下,不需要自定義上傳請求,組件內(nèi)置了上傳請求,如果個人有需求可以自定義上傳請求,子定義上傳請求,是在文件限制流程后,檢查是否有自定義請求方法,如果存在就將文件傳入自定義請求方法。 組件實現(xiàn):
// 上傳文件 const uploadFiles = (files) => { if (files.length === 0) return const { limit, multiple, accept, httpRequest } = props // 是否多文件限制,主要用于拖拽和粘貼上傳中 if (!multiple) { files = Array.from(files).slice(0, 1) } // 文件數(shù)量 if (limit && files.length > limit) { /*具體大家需要的邏輯可自行定義*/ return } // 文件類型限制 if (accept) { files = filesFiltered(Array.from(files), accept) } //在文件符合條件后執(zhí)行上傳方法 // 自定義上傳方法調(diào)用 if(httpRequest) { return httpRequest(files) } }組件應用: 注意點: 通過自定義上傳方法實現(xiàn)時,在原來組件上的屬性 action 無效
點擊上傳{{progressval}} %
總結
通過以上可以實現(xiàn)一個支持多種交互方式的文件上傳組件,同時也將 element-plus 中文件上傳的流程做了一個學習,因為該組件的實現(xiàn)過程就是參考了 element-plus 的實現(xiàn),在 element-plus 上傳的基礎上添加了粘貼上傳交互,該組件的實現(xiàn)重在交互方式,各個樣式風格通過插槽自定義。
-
文件
+關注
關注
1文章
570瀏覽量
24821 -
組件
+關注
關注
1文章
517瀏覽量
17922
原文標題:前端文件上傳的幾種交互造輪子
文章出處:【微信號:OSC開源社區(qū),微信公眾號:OSC開源社區(qū)】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論