当然这一切的一切肯定是基于IE8不支持的新特性,哈哈哈
难吗
回答是肯定的,难! 任何不舍得花时间去研究去思考的事情都比较难,难在自己身上。
插件都是人写出来的,那么为什么自己不可以成为那一类人,而总是去争当用轮子的人。
起因
跟大部分人一样,刚开始涉猎特定语言方面的技能,总是需要用别人的轮子推车。用JavaScript的话来说,那就是 各种插件各种库。我也一样,从一年初入前端,到现在也有一年多点时间了。面对各种开发需求,在个人能力范围没达到要求的时候也是需要去各大网站查找对应的功能插件。从一开始就有着一颗心,什么都系都想通过原生JS去实现,想要掌握这门语言的特性。但是在公司生产过程中,我发现能力的不足与特殊功能开发效率的底下是我这个初级开发者无法跨过的,得用插件、库。
而现在,在一定的能力支撑与一点时间的牺牲,我发现我更乐于去做替代插件、库的工作;同样带来的好处就是,有任何问题我知道为什么会出现,怎么修复以及怎么避免。就如同乐观心态(给钱让你coding)一样,各种好处给你,不要白不要。
开始
xxx:叽里呱啦说了一大堆,跟标题有关系吗,Show me the code
me: 那啥,咱不是白话的嘛,code可能就放关键代码怎么样。。
流程
- 首先的要一个 input[type=file](如果要在移动端使用 还需要加上camera 属性,多选 multiple)
- 处理代理点击 (file的样式太丑还不能改,1,代理点击 2,在file上面浮一层 元素 pointer-event:none)
- 监听file的 change 事件(*注意点A)
- 处理文件,返回内容
(附加:拖拽上传)
代理点击
在低版本的IE下,浏览器处于安全原则,必须需要用户点击file才能触发文件选择。所以才有了pointer-event:none这一种解决方案。当然如果是支持高版本的浏览器,这些都不用care,代理触发、点击失效想怎么来就怎么来
监听
file再被触发点击之后,会弹出文件框(本地相册)提供用户选择,当用户选择之后触发了 file 的 change 事件,这个时候就可以拿到用户所选择的内容了,与一般 <input> this.value不同,file 获取 文件内容是 通过 this.files,而这个 files 跟 arguments,NodeList 一样,是个类数组。每个file文件能都访问到的属性有:
这样 我们可以通过 file[accept] 与 File.type 进行双重验证,以及大小验证等
** 注意 ** 如果上传连续选择同一个文件,那么将不触发change事件,对啊,两次都一样,怎么能叫change,所以没有将上传信息返回开发者操作时,需要将file置空。然而在这个时候,IE高版本就跑出来给你找问题了,你从有数据到空数据,那是不是也是change啊,它就给你触发一次change事件,这个时候就需要在change事件中,判断this.files.length了。
处理文件
在监听到change事件,拿到files之后,就可以开始对files进行各种验证与操作了,验证就不仔细说了,只是需要注意的一点是,验证不通过,给出提示,结束函数时,记得置空file,不然再选择同样的文件,不会触发。
处于安全性的考虑,this.files是不能够被修改的,也就是说你不能直接的操作它,只能通过Array将他内部的file复制到一个数组中进行操作,并作为结果返回给开发者。
//生成本地预览
window.URL.createObjectURL(file);
而开发者拿到通过验证的files之后,可以通过 new FormData() 进行数据上传,一般来说都是通过ajax
var form_data = new FormData();
form_data.append(追加key,追加value);
returnFiles.forEach( item => {
form_data.append(上传key,item)
})
而通过 ajax上传文件 需要注意一点是 ,是要 禁止处理发送的数据,与设置Content-Type请求头,让他们自适应去
关于拖拽上传
那就更简单了~ 哈? 更简单???
步骤
- 禁止浏览器默认行为,就是拖拽文件后自动打开改文件,防止用户没有拖拽到目标区,结果页面跳转了
- 监听制动拖拽容器的 drop 行为
- 通过监听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;
})
结束语
这样,你不就知道是怎么实现得了嘛,插件? 为何我不试试?