當然這一切的一切肯定是基于IE8不支持的新特性,哈哈哈
難嗎
回答是肯定的,難! 任何不舍得花時間去研究去思考的事情都比較難,難在自己身上。
插件都是人寫出來的,那么為什么自己不可以成為那一類人,而總是去爭當用輪子的人。
起因
跟大部分人一樣,剛開始涉獵特定語言方面的技能,總是需要用別人的輪子推車。用JavaScript的話來說,那就是 各種插件各種庫。我也一樣,從一年初入前端,到現(xiàn)在也有一年多點時間了。面對各種開發(fā)需求,在個人能力范圍沒達到要求的時候也是需要去各大網(wǎng)站查找對應的功能插件。從一開始就有著一顆心,什么都系都想通過原生JS去實現(xiàn),想要掌握這門語言的特性。但是在公司生產(chǎn)過程中,我發(fā)現(xiàn)能力的不足與特殊功能開發(fā)效率的底下是我這個初級開發(fā)者無法跨過的,得用插件、庫。
而現(xiàn)在,在一定的能力支撐與一點時間的犧牲,我發(fā)現(xiàn)我更樂于去做替代插件、庫的工作;同樣帶來的好處就是,有任何問題我知道為什么會出現(xiàn),怎么修復以及怎么避免。就如同樂觀心態(tài)(給錢讓你coding)一樣,各種好處給你,不要白不要。
開始
xxx:嘰里呱啦說了一大堆,跟標題有關系嗎,Show me the code

me: 那啥,咱不是白話的嘛,code可能就放關鍵代碼怎么樣。。
流程
- 首先的要一個 input[type=file](如果要在移動端使用 還需要加上camera 屬性,多選 multiple)
- 處理代理點擊 (file的樣式太丑還不能改,1,代理點擊 2,在file上面浮一層 元素 pointer-event:none)
- 監(jiān)聽file的 change 事件(*注意點A)
- 處理文件,返回內(nèi)容
(附加:拖拽上傳)
代理點擊
在低版本的IE下,瀏覽器處于安全原則,必須需要用戶點擊file才能觸發(fā)文件選擇。所以才有了pointer-event:none這一種解決方案。當然如果是支持高版本的瀏覽器,這些都不用care,代理觸發(fā)、點擊失效想怎么來就怎么來
監(jiān)聽
file再被觸發(fā)點擊之后,會彈出文件框(本地相冊)提供用戶選擇,當用戶選擇之后觸發(fā)了 file 的 change 事件,這個時候就可以拿到用戶所選擇的內(nèi)容了,與一般 <input> this.value不同,file 獲取 文件內(nèi)容是 通過 this.files,而這個 files 跟 arguments,NodeList 一樣,是個類數(shù)組。每個file文件能都訪問到的屬性有:

這樣 我們可以通過 file[accept] 與 File.type 進行雙重驗證,以及大小驗證等
** 注意 ** 如果上傳連續(xù)選擇同一個文件,那么將不觸發(fā)change事件,對啊,兩次都一樣,怎么能叫change,所以沒有將上傳信息返回開發(fā)者操作時,需要將file置空。然而在這個時候,IE高版本就跑出來給你找問題了,你從有數(shù)據(jù)到空數(shù)據(jù),那是不是也是change啊,它就給你觸發(fā)一次change事件,這個時候就需要在change事件中,判斷this.files.length了。
處理文件
在監(jiān)聽到change事件,拿到files之后,就可以開始對files進行各種驗證與操作了,驗證就不仔細說了,只是需要注意的一點是,驗證不通過,給出提示,結束函數(shù)時,記得置空file,不然再選擇同樣的文件,不會觸發(fā)。
處于安全性的考慮,this.files是不能夠被修改的,也就是說你不能直接的操作它,只能通過Array將他內(nèi)部的file復制到一個數(shù)組中進行操作,并作為結果返回給開發(fā)者。
//生成本地預覽
window.URL.createObjectURL(file);
而開發(fā)者拿到通過驗證的files之后,可以通過 new FormData() 進行數(shù)據(jù)上傳,一般來說都是通過ajax
var form_data = new FormData();
form_data.append(追加key,追加value);
returnFiles.forEach( item => {
form_data.append(上傳key,item)
})
而通過 ajax上傳文件 需要注意一點是 ,是要 禁止處理發(fā)送的數(shù)據(jù),與設置Content-Type請求頭,讓他們自適應去
關于拖拽上傳
那就更簡單了~ 哈? 更簡單???

步驟
- 禁止瀏覽器默認行為,就是拖拽文件后自動打開改文件,防止用戶沒有拖拽到目標區(qū),結果頁面跳轉了
- 監(jiān)聽制動拖拽容器的 drop 行為
- 通過監(jiān)聽drop 拿到 e.dataTransfer.files 這就是跟file 一模一樣的 格式了。當然后你可能需要兼容一下 e 在不同瀏覽器的差異了
- 跟file 一樣 處理文件 沒了。。。
//脫離 dragleave
document.addEventListener('dragleave',function(e){
e.preventDefault();
//或則
window.event.returnValue = false;
return false;
})
// 拖放后 drop
// 拖進 dragenter
// 拖來拖去 dragover
// 這四個都要禁止
拖拽受體.addEventListener('drop',function(e){
var _files = e.originalEvent.dataTransfer.files;
})
結束語
這樣,你不就知道是怎么實現(xiàn)得了嘛,插件? 為何我不試試?