前端图片上传问题整理
問題整理
最近做的項目是要實現多張上傳圖片的功能,可以刪除圖片,選中多張圖片并重新上傳,在實踐過程中遇到了以下問題:
1.圖片效果
為實現圖1中的效果,需要解決兩個問題:第一個是如何進行圖片布局;第二個是如何實現刪除及選中效果。
- 圖片布局
對于圖片布局,利用<img><span><input>這三個標簽是可以實現圖1中的樣式的,但是需要進行樣式調整,而且圖片多張進行排列的時候間距及布局不好把握。
在插入圖片方面,HTML5提供了<figure>標簽來插入圖片,并提供<figcaption>來描述圖片。
- 刪除及選中效果
在插件樣式方面,boostrap提供了豐富的插件樣式,可以實現圖1中需要的刪除及選中效果。
需要注意的是,刪除的叉號標志需要定位到圖片的右上角,可以利用絕對定位的方式來實現。選中效果則需要以下三步來完成:將對號定位到圖片中間位置,為對號添加藍色圓形填充,將對號定位到圓形填充的中央。
2.上傳同一張圖片
利用<input type="file">上傳圖片時,當選中了一張圖片點擊取消或者選中圖片并打開,然后刪除該圖片,再選中剛剛的圖片是無法出發onChange或onClick事件的。
這種現象產生的原因是上傳文件的時候,會將當前的文件路徑保存在<input>的value中,點擊取消其value值不會改變,所以導致第二次上傳同一張圖片的時候,是同一個value,因此無法觸發函數。
- 解決辦法
a. 刪除原來的<input>框,重新生成一個<input>框,并綁定onChange事件。
b. 每次上傳文件之后,手動修改input框的value值。
在開發過程中,要盡量避免直接操縱DOM元素的方法,因此對于以上兩種解決辦法,傾向于采取第二種。
在<input>框中,綁定ref,用于獲取DOM元素。
然后,在上傳文件后,將value值清空。
this.input.value = '';3.讀取多張上傳文件
利用<input type="file">上傳圖片,如果添加了"webkitdirectory"屬性,則可以一次上傳多張圖片,此時涉及到如何讀取多張圖片并展示。
首先,需要獲取文件信息,<input>會將上傳的文件信息以數組的形式保存在event中,可以通過event.target.files來獲取文件信息。
然后,new一個FileReader對象來讀取文件,FileReader主要有3個方法如下列表展示。
| readAsBinaryString | file | 將文件讀取為二進制碼 |
| readAsDataURL | file | 將文件讀取為 DataURL |
| readAsText | file, [encoding] | 將文件讀取為文本 |
對于圖像的讀取,選擇readAsDataURL方法,讀取讀像的base64編碼,用于圖像的展示。當文件讀取成功后,需調用FileReader的onload方法來進行圖片讀取成功之后的操作。
onChange = e => {let $input = e.target;const files = $input.files;const reader = new FileReader();reader.readAsDataURL(files[0]);reader.onload = () => {img.push(this.result); //圖像base64編碼保存到數組中}需要注意的是,當一次上傳多張圖片時,需要將files數組中的多個值全部讀出來,最容易想到的辦法是外層加一個for循環,每次循環讀取。但是這樣沒法全部按順序讀取圖片,其原因是reader.onload()事件是異步觸發的。
可以通過遞歸調用讀取圖片函數來解決這個問題:
4.阻止單擊事件
項目中有這樣一個應用場景,單擊圖片呈選中狀態,雙擊圖片需要展示圖片的原圖。首先想到的是通過給圖片綁定單擊事件和雙擊事件來出發選中及展示原圖。
<img src={content} onClick={this.checkImage} onDoubleClick={this.showImage}>
但是這樣存在的問題是雙擊圖片時,會先觸發單擊事件,然后再出發雙擊事件,而我需要的是雙擊時只觸發雙擊事件。這樣的話就需要給單擊事件一個延遲時間,在時間范圍內點擊圖片不會出發單擊事件,也就解決了這個問題。
const timer = null; checkImage = () => {clearTimeout(timer);timer = setTimeout(function(){//do something},250); } showImage = () => {clearTimeout(timer);// do something }值得注意的是,在setTimeout定時器中,this指針會獲取不到,因此如果需要在定時器函數中用到this指針,需要實現聲明一個新的變量const _this=this;來存儲this指針。
5.get傳參問題
通過window.open()打開鏈接的時候,需要將參數傳到新頁面,在新頁面需要接收這個參數并進行處理。這個時候可以通過window.location這個對象的屬性來接收并處理參數。該對象包含的屬性有以下幾種:
| hash | 從井號 (#) 開始的 URL(錨) |
| host | 主機名和當前 URL 的端口號 |
| hostname | 當前 URL 的主機名 |
| href | 完整的 URL |
| pathname | 當前 URL 的路徑部分 |
| port | 當前 URL 的端口號 |
| protocol | 當前 URL 的協議 |
| search | 從問號 (?) 開始的 URL(查詢部分) |
當利用window.location.search來獲取參數的時候,需要注意兩點:
a. 需要用正則找到需要的參數。
window.location.search.substring(1).split("=")[1],如果有多個參數,還需要利用“&”進一步分割。
b. 參數中存在中文時會被編碼。
“./main.html?user=小明"該鏈接中存在中文字符,如果不解碼直接接收會接收到一串編碼,而不是想要的中文參數。因此,需要利用decodeURIComponent()進行解碼。
decodeURIComponent(window.location.search.substring(1).split("=")[1])
以上就是對最近遇到的問題的整理。
總結
以上是生活随笔為你收集整理的前端图片上传问题整理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java textpad_TextPad
- 下一篇: html语言中glyphicon,boo