UniApp+uView實現表單中的圖片批量上傳
技術概述
團隊項目的需求是:用戶在投訴的時候可以拍攝、多選上傳最多5張的照片,達到上限時,隱藏上傳按鈕;用戶可以預覽、刪除所選圖片,添加或刪除后的圖片數和預覽小圖要及時、正確地反映到界面上;最終圖片與投訴文字一起提交。
難點:在已有組件的基礎上改進為自己想要的樣子。
技術詳述
我在團隊開發中是否擔任了小程序的前端開發,因此以下敘述沒有涉及到圖片上傳的后端處理。
使用的是uView前端框架中的u-upload組件,使用方法可以參考uView的官方文檔:Upload組件官方文檔說明。在uni-app插件市場可以下載到uview-ui安裝包,具體配置方法不作贅述。解壓后在components下可以找到組件源碼,注釋里給出了更詳細的參數配置方法以供參考,也可以閱讀其實現代碼加深理解。
- 界面代碼
直接引用組件,參照官方文檔,結合自己的需求修改各種參數,例如上傳圖片的按鈕、上傳時的遮罩層、刪除按鈕等都是可以進行個性化配置的。這里我們將自動上傳打開(auto-upload="true"),這樣用戶選擇完圖片后系統即返回一個url。等待用戶將投訴文本填寫完畢,再將圖片url與文字一並提交。
- 數據存儲與部分參數配置
如圖所示,action為服務器地址,form為表單上傳的數據結構(是一個model),其中攜帶兩個參數,反饋文本與圖片url。fileList是組件自帶的圖片存放列表,imageList則是我們額外使用的用於傳遞圖片url集合的數組。
- 處理函數
- on-list-change:當內部文件列表被加入文件、移除文件,或手動調用clear方法時觸發.返回(lists, name),lists為內部文件變化之后的列表,name為通過props傳遞的index參數。
- on-success:圖片上傳成功時觸發,data為服務器返回的數據。
- on-remove:移除圖片時觸發,name為通過props傳遞的index參數。
函數都放在methods里,並在界面代碼中與事件綁定。上傳組件請求后端服務器后接收返回的圖片url,組件會自動更新預覽列表,我們則將url以字符串的形式存入到表單的提交參數中,剩下的切割等工作交給后端或者需要顯示反饋圖片的Web端處理。
onListChange:這里我們直接獲取所返回的lists的長度得到實時選擇圖片數。
onSuccess:具體的說明都在注釋中給出。
onRemove:刪除圖片時,通過slice切分,准確獲得指定下標圖片被刪除后的結果。
在數組中 slice(i,[j])
i為開始截取的索引值,負數代表從末尾算起的索引值,-1為倒數第一個元素
j為結束的索引值,缺省時則獲取從i到末尾的所有元素
參數返回:
返回索引值從i到j的數組,原數組不改變
- 流程圖
問題和解決過程
-
坑1:開發過程中會出現如下情況:在小程序開發版與體驗版的調試過程中,圖片上傳沒有問題;但發布后的線上版本,圖片上傳請求后端接口失敗。
原因:微信小程序里如果涉及到文件上傳、下載等,發布上線版本時,需要到微信公眾號官網,小程序開發管理里面,配置服務器域名,才能使相關功能的正常運行。就比如圖片上傳。
-
坑2:允許的圖片后綴可以主動配置,默認為['png', 'jpg', 'jpeg', 'webp', 'gif'],但部分手機型號會出現圖片后綴為大寫的情況,因此需要主動加上,否則可能也會導致上傳失敗。
limitType: ['png', 'jpg', 'jpeg', 'webp', 'gif', 'JPG', 'PNG', 'JPEG', 'GIF', 'WEBP'],
-
坑3:清空表單內容時最好將下面幾句一並寫上,不然可能會出現部分數據沒有重置的情況。
-
坑4:記得使用並且善用JSON.stringify,否則常常會得到一個空串。遇到時就可以檢查是否忘記了這一步。還有可能是服務器返回的數據結構與你寫的獲取代碼不一致,比如服務器返回的是data.data.pictureUrl,包了兩層data,只寫data.pictureUrl的話就漏了一層。
-
坑5:處理添加與刪除圖片邏輯的時候一定要小心,參照上圖代碼,善用控制台測試。否則該組件會出現添加或刪除圖片后多出一張空白預覽圖的情況。
-
坑6:表單組件u-form的填寫規則(例如填寫字數上限)要在onReady()生命周期中設置,否則無效。
<u-form :model="form" @submit="submit" :rules="rules" ref="uForm" >
this.$refs.uForm.setRules(this.rules);
總結
uView是一個基於UniApp的開源前端模板,其存在本身較“新”,因此肯定存在着bug與設計上的不足。在使用其中的組件時勢必會遇到不少問題,可能百度都難以找到與自己的情況完全相符的解決方法,這時候就可以多多仔細閱讀官方文檔與源代碼,了解其內部邏輯;如果實在無法解決就先跳脫出去,想想是不是前端代碼以外的問題,或者是否有替代方案。