摘要:在日常項(xiàng)目開(kāi)發(fā)中,圖片上傳是一個(gè)十分常見(jiàn)的場(chǎng)景。在圖片拖拽上傳這個(gè)業(yè)務(wù)場(chǎng)景中,被拖拽元素為頁(yè)面外部的圖片文件,故此處僅用到目標(biāo)元素的各個(gè)事件。具體實(shí)現(xiàn)代碼如下至此,圖片上傳的常用知識(shí)點(diǎn)以梳理完畢,歡迎補(bǔ)充。
在日常項(xiàng)目開(kāi)發(fā)中,圖片上傳是一個(gè)十分常見(jiàn)的場(chǎng)景。而現(xiàn)在的各種UI框架都提供了自己的上傳組件,網(wǎng)上第三方的上傳組件也多如牛毛??赡苣阍缫蚜?xí)慣了直接使用這些現(xiàn)成的組件,然而對(duì)于其具體的實(shí)現(xiàn),卻并未深入解析。本文將通過(guò)簡(jiǎn)單的代碼,為你解析圖片上傳的各個(gè)知識(shí)點(diǎn)。
樣式自定義既然是上傳,肯定需要使用到標(biāo)簽了。然而,默認(rèn)的input到標(biāo)簽樣式不僅單一,且在各個(gè)瀏覽器下的表現(xiàn)也不相同,所以通常需要對(duì)input進(jìn)行樣式自定義。但標(biāo)簽對(duì)于樣式的修改并不十分友好。解決方法很多,最常用的是將標(biāo)簽隱藏,然后通過(guò)一個(gè)標(biāo)簽進(jìn)行關(guān)聯(lián),然后直接修改標(biāo)簽的樣式來(lái)實(shí)現(xiàn)。代碼如下:
圖片校驗(yàn)
在上傳之前,一般會(huì)對(duì)文件進(jìn)行各種校驗(yàn),例如文件類(lèi)型,大小,格式,尺寸等。
其中文件類(lèi)型,可通過(guò)設(shè)置標(biāo)簽的accept來(lái)指定文件類(lèi)型。但accept屬性并不能完全禁止用戶(hù)上傳指定類(lèi)型之外的文件。故可以通過(guò)上傳文件的各個(gè)屬性進(jìn)行校驗(yàn)攔截。校驗(yàn)前,我們需要通過(guò)change事件的事件對(duì)象來(lái)獲取到上傳的文件:
event.target.files
可以獲取到上傳文件列表。列表中對(duì)象包含如下信息:
{ lastModified: 1524153515000 lastModifiedDate: Thu Apr 19 2018 23:58:35 GMT+0800 (中國(guó)標(biāo)準(zhǔn)時(shí)間) {} name: "589adfbfe821c.jpg" size: 1357444 type: "image/jpeg" webkitRelativePath: "" }
從該對(duì)象中,我們可以獲取到文件大小,文件類(lèi)型,文件名等信息,從而可以在上傳之前對(duì)這些信息進(jìn)行校驗(yàn),從而攔截掉不合法的文件。
然而,從file對(duì)象中,我們并不能獲取圖片的尺寸信息。而在我們的業(yè)務(wù)中,很多場(chǎng)景都需要限制上傳圖片的尺寸為某一個(gè)固定值,或者是某一個(gè)比例。以減少后期顯示時(shí)的適配問(wèn)題。要實(shí)現(xiàn)對(duì)上傳圖片尺寸對(duì)校驗(yàn),我們需要使用到FileReader和Image。
FileReader對(duì)象允許Web應(yīng)用程序異步讀取存儲(chǔ)在用戶(hù)計(jì)算機(jī)上的文件。
Image()函數(shù)將會(huì)創(chuàng)建一個(gè)新的HTMLImageElement實(shí)例。它的功能等價(jià)于document.createElement("img")。
這里,我們需要用到fileReader的readAsDataURL()方法來(lái)讀取上傳文件信息,通過(guò)onload處理事件來(lái)獲取讀取到的文件信息。如下:
const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = e => { console.log(e.target.result) }
代碼中,file為我們之前獲取到的文件列表files中的文件對(duì)象。e.target.result為讀取到到文件內(nèi)容。
之后通過(guò)new Image()函數(shù)創(chuàng)建一個(gè)新的HTMLImageElement實(shí)例,并將該實(shí)例的src賦值為fileReader讀取到到文件內(nèi)容。即可得到一個(gè)該文件的HTMLImageElement實(shí)例,通過(guò)該實(shí)例,我們便可以讀取到該圖片的尺寸信息。具體代碼如下:
const image = new Image(); image.src = e.target.result; image.onload = () => { console.log(image.width, image.height); }圖片上傳預(yù)覽
在之前的開(kāi)發(fā)中,圖片上傳顯示通常會(huì)采用先將文件上傳,預(yù)覽圖片直接展示上傳到服務(wù)器中到圖片來(lái)實(shí)現(xiàn),但這樣無(wú)法達(dá)到上傳前預(yù)覽該圖片的目的,且會(huì)造成許多垃圾圖片的上傳。
通過(guò)前面對(duì)于獲取圖片尺寸研究。相信你能很快想到一種更加優(yōu)雅的圖片預(yù)覽方案,既然我們已經(jīng)獲取到了該文件的HTMLImageElement實(shí)例,那么我們直接將該實(shí)例append到頁(yè)面的容器Dom中不久行了?;蛘咧苯訉@取到的文件設(shè)置到已存在的image標(biāo)簽的src屬性中。圖片上傳預(yù)覽就是這么簡(jiǎn)單。
圖片上傳與上傳進(jìn)度展示圖片的上傳,我們可以直接通過(guò)form標(biāo)簽搭配表單的submit()方法來(lái)實(shí)現(xiàn)圖片的上傳。然而,這樣我們就無(wú)法在上傳前進(jìn)行上傳文件的校驗(yàn)與攔截。同時(shí)需要用戶(hù)主動(dòng)觸發(fā)提交操作。要想讓我們之前做的上傳前的攔截工作不白做,我們需要去在合適的時(shí)候,主動(dòng)觸發(fā)文件的上傳操作。
這里,需要使用到FormData對(duì)象,來(lái)將入?yún)?duì)象數(shù)據(jù)轉(zhuǎn)為表單數(shù)據(jù)。
FormData對(duì)象用以將數(shù)據(jù)編譯成鍵值對(duì),以便用XMLHttpRequest來(lái)發(fā)送數(shù)據(jù)。其主要用于發(fā)送表單數(shù)據(jù),但亦可用于發(fā)送帶鍵數(shù)據(jù)(keyed data),而獨(dú)立于表單使用。如果表單enctype屬性設(shè)為multipart/form-data ,則會(huì)使用表單的submit()方法來(lái)發(fā)送數(shù)據(jù),從而,發(fā)送數(shù)據(jù)具有同樣形式。
首先我們創(chuàng)建一個(gè)formData對(duì)象,然后通過(guò)append() 方法來(lái)添加字段。如下:
const formData = new FormData(); formData.append("file", file);
注意,formData雖然為一個(gè)對(duì)象,但通過(guò)console.log卻無(wú)法打印出其具體的值,只會(huì)得到FormData {}。
接下來(lái)創(chuàng)建一個(gè)XMLHttpRequest對(duì)象,用來(lái)發(fā)送ajax請(qǐng)求。并且通過(guò)該XMLHttpRequest對(duì)象的upload.onprogress方法,可以實(shí)時(shí)獲取到上傳信息,并進(jìn)一步獲取到上傳的進(jìn)度。具體代碼如下:
const client = new XMLHttpRequest() client.open("POST", uploadUrl) client.upload.onprogress = function(e) { if (e.lengthComputable) { let total = e.total; let loaded = e.loaded; let percentage = parseFloat(loaded / total).toFixed(2); } } client.send(formData)
上面代碼中,uploadUrl為上傳的URL。通過(guò)upload.onprogress的事件對(duì)象,可以獲取到當(dāng)前進(jìn)度已上傳的文件大小以及完整文件大小,通過(guò)這兩個(gè)大小參數(shù),可以很容易計(jì)算出已上傳文件的比例,之后是顯示上傳進(jìn)度條、還是展示進(jìn)度數(shù)據(jù),就可以隨意操作了。
拖拽上傳除了傳統(tǒng)的點(diǎn)擊選擇上傳文件外,拖拽文件上傳也是一個(gè)十分常見(jiàn)的場(chǎng)景。要使用拖拽上傳,就需要使用H5的拖放方法drop 和 drag方法。除了這兩個(gè)主要的方法外,還有拖放的不同階段觸發(fā)的多個(gè)方法,常用的拖拽方法如下:
ondragstart 事件:當(dāng)拖拽元素開(kāi)始被拖拽的時(shí)候觸發(fā)的事件(作用對(duì)象為被拖曳元素)
ondrag:在元素拖動(dòng)期間不停的觸發(fā)該事件,與touchmove事件類(lèi)似。(作用對(duì)象為被拖曳元素)
ondragend 事件:當(dāng)拖拽完成后觸發(fā)的事件(作用對(duì)象為被拖曳元素)
ondragenter 事件:當(dāng)拖曳元素進(jìn)入目標(biāo)元素的時(shí)候觸發(fā)的事件(作用對(duì)象為目標(biāo)元素)
ondragover 事件:拖拽元素在目標(biāo)元素上移動(dòng)的時(shí)候觸發(fā)的事件(作用對(duì)象為目標(biāo)元素)
ondragleave 事件:拖拽元素在目標(biāo)元素上移動(dòng)的時(shí)候觸發(fā)的事件(作用對(duì)象為目標(biāo)元素)
ondrop 事件:被拖拽的元素在目標(biāo)元素上同時(shí)鼠標(biāo)放開(kāi)觸發(fā)的事件(作用對(duì)象為目標(biāo)元素)
拖拽的各個(gè)事件類(lèi)似與touch事件的各個(gè)階段。然而需要注意的是,拖拽的各個(gè)事件,有著自己的作用對(duì)象,作用對(duì)象分為‘被拖拽元素’和‘目標(biāo)元素’。被拖拽元素 為拖拽的那個(gè)Dom元素,主要使用在頁(yè)面內(nèi)Dom拖拽移動(dòng)的場(chǎng)景。目標(biāo)元素為接收被拖拽元素的元素區(qū)域。當(dāng)被拖拽元素進(jìn)入到該區(qū)域,便會(huì)觸發(fā)目標(biāo)對(duì)象的一系列事件。
在圖片拖拽上傳這個(gè)業(yè)務(wù)場(chǎng)景中,被拖拽元素為頁(yè)面外部的圖片文件,故此處僅用到目標(biāo)元素的各個(gè)事件。我們可以通過(guò)這些事件來(lái)修改目標(biāo)區(qū)域樣式等。核心的兩個(gè)事件為ondragover和ondrop事件。可能你覺(jué)得我只需要在松開(kāi)鼠標(biāo)時(shí)獲取拖拽的文件就行,因此只需要使用ondrop事件就行了?但是,由于瀏覽器的默認(rèn)行為,ondrop事件并不會(huì)被觸發(fā)。因此,需要使用e.preventDefault(); 來(lái)阻止掉 ondropover的瀏覽器默認(rèn)事件,從而保證ondrop事件的觸發(fā)。通過(guò)ondrop事件的事件對(duì)象,我們可以獲取到跟event.target.files相同的文件列表,獲取方法為event.dataTransfer.files;然而,當(dāng)你這么寫(xiě)完之后,進(jìn)行拖拽之后,你會(huì)發(fā)現(xiàn)瀏覽器自動(dòng)跳轉(zhuǎn)到了該圖片的預(yù)覽頁(yè)。這也是由于瀏覽器的默認(rèn)行為導(dǎo)致,因此也需要使用e.preventDefault();來(lái)阻止掉瀏覽器的默認(rèn)行為。這樣,便可以進(jìn)行后續(xù)的文件校驗(yàn)操作來(lái)。
具體實(shí)現(xiàn)代碼如下:
至此,圖片上傳的常用知識(shí)點(diǎn)以梳理完畢,歡迎補(bǔ)充。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/99032.html
摘要:在日常項(xiàng)目開(kāi)發(fā)中,圖片上傳是一個(gè)十分常見(jiàn)的場(chǎng)景。在圖片拖拽上傳這個(gè)業(yè)務(wù)場(chǎng)景中,被拖拽元素為頁(yè)面外部的圖片文件,故此處僅用到目標(biāo)元素的各個(gè)事件。具體實(shí)現(xiàn)代碼如下至此,圖片上傳的常用知識(shí)點(diǎn)以梳理完畢,歡迎補(bǔ)充。 在日常項(xiàng)目開(kāi)發(fā)中,圖片上傳是一個(gè)十分常見(jiàn)的場(chǎng)景。而現(xiàn)在的各種UI框架都提供了自己的上傳組件,網(wǎng)上第三方的上傳組件也多如牛毛??赡苣阍缫蚜?xí)慣了直接使用這些現(xiàn)成的組件,然而對(duì)于其具體的...
摘要:責(zé)編現(xiàn)代化的方式開(kāi)發(fā)一個(gè)圖片上傳工具前端掘金對(duì)于圖片上傳,大家一定不陌生。之深入事件機(jī)制前端掘金事件綁定的方式原生的事件綁定方式有幾種想必有很多朋友說(shuō)種目前,在本人目前的研究中,只有兩種半兩種半還有半種的且聽(tīng)我道來(lái)。 Ajax 與數(shù)據(jù)傳輸 - 前端 - 掘金背景 在沒(méi)有ajax之前,前端與后臺(tái)傳數(shù)據(jù)都是靠表單傳輸,使用表單的方法傳輸數(shù)據(jù)有一個(gè)比較大的問(wèn)題就是每次提交數(shù)據(jù)都會(huì)刷新頁(yè)面,用...
摘要:馬爾代夫之行重頭戲這一年的工作情況這一年,個(gè)人感覺(jué)還是做了不少事情,主要集中在我們公司的前端領(lǐng)域,同時(shí)也給整個(gè)技術(shù)團(tuán)隊(duì)不少的建議,引入了不少新的東西和方式,總結(jié)起來(lái)比較重要的在下面五個(gè)方面。 如果想看技術(shù)相關(guān)的,下拉到后面的重頭戲就是了。 一個(gè)活動(dòng)頁(yè)面 在15年末的時(shí)候,加入到羅輯思維,剛過(guò)來(lái)就接手了一個(gè)微信朋友圈要傳播的活動(dòng)頁(yè)面,效果頁(yè)面大概和當(dāng)時(shí)錘子手機(jī)的活動(dòng)頁(yè)面漂亮的不像實(shí)力派類(lèi)...
閱讀 2039·2021-11-23 09:51
閱讀 930·2021-11-19 09:40
閱讀 885·2021-10-27 14:20
閱讀 5221·2021-10-09 09:52
閱讀 3366·2021-10-09 09:44
閱讀 1783·2021-10-08 10:05
閱讀 5293·2021-09-09 11:47
閱讀 3550·2019-08-30 12:47