当前位置: 首页 > Web前端 > HTML5

上传组件如何设计?

时间:2023-04-05 14:17:43 HTML5

上传组件设计的目的是解决用户上传文件的方便,但是中后台上传组件的场景是多种多样的,所以可扩展性是上传组件的另一个方面这是不容忽视的。方面。也是为了大家更容易理解,我就从最原始的input标签submit开始这段代码的作用:先选中一个文件,然后点击提交将一个文件POST到一个界面。虽然代码不多,但是在实际使用中值得吐槽的点还是很多的。这里有两点需要重点关注。每个浏览器的性能是不同的。UI难看不说,各个主流浏览器上的文案基本都不一样,IE下的变化好像有点大。我们可能期望组件在任何浏览器下都具有一致的交互和UI。文件上传后,页面会刷新,导致体验问题。原文件上传是通过formpost方式上传的。上传完成后,整个页面会被重定向到该动作的地址。现在大家都习惯ajax进行数据提交,因为不需要重新加载页面就可以带来整个页面的数据更新,无刷新更新的体验会大大提升。我打算把整部电影分成两段来谈谈这个问题。分叉点会在2012年左右开始,因为html5会在这个时间左右逐渐得到现代浏览器的支持。这两个部分称为传统解决方案和现代解决方案。传统的解决方案是UI一致性问题。我们期望在任何浏览器中都具有相同的样式,例如按钮的样式上传文件将input设置为透明并覆盖按钮,让用户以为点击了按钮,但实际上点击了按钮上的input。这样就可以造成用户可以通过点击按钮来选择文件的“错觉”。搜索按钮实际上定位了输入。详细代码可以看这里:https://github.com/alibaba-fu...不刷新上传我们期望选择文件后立即上传文件。上传完成后,页面会直接显示上传状态。UploadFile提交时,表单指定目标到相应的iframe上传数据,使表单的数据通过隐藏的iframe提交。constdoc=this.refs.iframe.contentDocument;//获取iframeconstscript=doc.getElementsByTagName('script')[0];//清除iframe中无用的scriptif(script&&script.parentNode===doc.body){doc.body.removeChild(script);}constresponse=JSON.parse(doc.body.innerHTML);//获取返回的内容并解析成JSON,因为iframe上传后页面会整体刷新,然后通过监听iframe的onLoad事件获取返回的结果。获取返回内容然后反馈到主页面的代码可以看这里:https://github.com/alibaba-fu...现代上传解决方案html5出来后,可以直接获取通过输入File文件对象,然后将File封装成FormData,通过ajax提交到后台接口,实现文件上传。UI一致性问题不需要覆盖按钮上的input,而是通过监听父节点的click事件,在事件中触发input的click方法。

其实我不仅可以在div里面放按钮,还可以放任何元素,这样我们就可以制作上传任何形状的按钮。这里有几个例子Cardstatus上传文件
上传面板点击或拖拽文件到虚线框上传支持docx,xls,PDF,rar,zip,PNG,JPG等类型的文件
无刷新上传的原理是将File对象封装成FormData,然后提交给后台接口以ajax的形式。直接上传代码:functionupload(file){constxhr=newXMLHttpRequest();//上传进度xhr.upload.onprogress=functionprogress(e){};//上传状态xhr.onload=functiononload(){};constformData=newFormData();//将要上传的文件对象添加到formDataformData.append('filename',file);//指定api接口和上传方式xhr.open('POST','/api/upload',true);//开始发送数据xhr.send(formData);}以上就是一个大致的流程,在formData中添加一个文件对象,然后通过XMLHttpRequest将formData发送到指定接口/api/upload。详细的代码可以看这里https://github.com/alibaba-fu...现实中,为了兼容ie9,我们还需要封装一个uploader,先支持html5,然后自动切换到iframeie9下解决。一个通用的React上传组件方案上面我们说了一个文件上传至少要经过两步:1.选择文件2.上传文件。并且我们已经具备了根据浏览器自动确定使用哪种兼容解决方案的能力。由此我们做了两个通用组件:Selecter文件选择器。任何组件都可以变成文件选择器并返回选择的File对象Uploader文件上传器。您可以使用api随意上传所选文件,并且可以监控进度。Selecter文件选择器封装的Selecter已经处理好输入和相关事件,你只需要关心放什么import{Upload,Button}from'@alifd/next';constSelecter=Upload.Selecter;classAppextendsReact.Comonent{handleSelect=(files)=>{//获取文件}render(){return上传文件}}如果想换成卡片样式,替换children即可,如下上传文件Uploader文件上传器将Selecter选中的File发送给Uploader,可以很方便的将文件上传到指定的接口。从“@alifd/next”导入{上传,按钮};constSelecter=Upload.Selecter;//文件选择器constUploader=Upload.Uploader;//文件上传类AppextendsReact.Comonent{uploader=newUploader({action:'/api/upload',//onProgress:this.onProgress//进度监控});handleSelect=(files)=>{//上传文件this.uploader.startUpload(files);}render(){returnUploadFile}}因为Selecter的UI可以自定义,所以Uploader的文件上传时机可以被随意控制。是的,Selecter和Uploader的结合可以适应任何场景和交互。调试demo见:https://codepen.io/frankqian/...比如我们可以通过Uploader自定义各种功能,比如做一个粘贴上传组件去除进度条装饰,代码写在less超过20行整个组件:import{Upload,Input}from'@alifd/next';constUploader=Upload.Uploader;//文件上传类AppextendsReact.Component{uploader=newUploader({action:'/api/upload',});//处理粘贴事件onPaste=e=>{constfiles=e.clipboardData.files;//获取粘贴的文件数据this.uploader.startUpload(files);//上传文件};render(){return;}}你可以在这里调试代码:https://codepen.io/frankqian/...进一步提取更通用的用法解决易用性问题的方法虽然Selecter和Uploader使用起来非常灵活,但你仍然需要自己写一些逻辑,将获取到的File对象和Uploader关联起来进行上传。我们最常见的文件上传交互方式是选择后开始上传,上传后反馈。因此,我们进一步抽取了常用的交互,比如单按钮、卡片、拖拽面板等,主要是沉淀常用的UI和上传交互,方便大部分场景使用。从'@alifd/next'导入{Upload,Button};classAppextendsReact.Comonent{handleChange=(file)=>{console.log(file.url);//直接获取图片url}render(){return
上传文件上传文件
}}以上结合业务线对于常用的上传方案和交互抽取的上传方式,我们进一步封装Selecter和Uploader,得到一个UI和交互相对固定的组件,使用起来更方便。阿里内部各个业务线的上传需求是多种多样的,FusionNext的上传组件必须考虑效率和能力的平衡。一个好的组件应该通过固定的组件解决80%的常见问题;剩下的20%可能每个业务线不一样,每个业务线可以通过扩展能力来支持。相关链接Fusion上传:https://fusion.design/compone...github:https://github.com/alibaba-fu...