当前位置: 首页 > 科技观察

前端进阶:原生JavaScript实现一个带进度监控的文件上传预览组件

时间:2023-03-15 00:06:23 科技观察

本文主要介绍如何使用原生js以面向对象的方式实现一个文件上传预览组件。、预览、读取进度等功能,并暴露相应的API,实现用户自定义需求,如文件上传、进度监控、自定义样式、读取成功回调等。组件设计架构如下:涉及的核心知识点如下:闭包:减少变量污染,缩短变量查找范围自执行函数文件API:读取、解析、监听文件事件DocumentFragmentAPI:主要用于优化dom操作minix:用于实现对象混合正则表达式:匹配文件类型类:类组件github地址使用原生js实现文件上传预览组件带进度监控Demo演示使用:scriptsrc="./js/xjFile.js">CSS代码:.xj-wrap{position:relative;display:inline-block;border:1pxdashed#888;width:200px;height:200px;border-radius:6px;overflow:hidden;}.xj-wrap::before{content:'+';font-size:36px;position:absolute;transform:translate(-50%,-50%);left:50%;top:50%;color:#ccc;}.xj-wrap.xj-pre-img{width:100%;高度:100%;背景重复:不重复;背景位置:中心中心;b背景大小:100%;}.xj-文件{位置:绝对;左:0;右:0;底部:0;顶部:0;不透明度:0;光标:指针;}js代码:(function(win,doc){functionxjFile(opt){vardefaultOption={el:doc.body,accept:'*',//格式按钮'image/jpg,image/gif'传clsName:'xj-wrap',beforeUpload:function(e){console.log(e)},onProgress:function(e){console.log(e)},onLoad:function(e){console.log(e)},onError:function(e){console.error('文件读取错误',e)}};//获取domif(opt.el){opt.el=typeofopt.el==='object'?opt.el:document.querySelector(opt.el);}this.opt=minix(defaultOption,opt);this.value='';this.init();}xjFile.prototype.init=function(){this.render();this.watch();}xjFile.prototype.render=function(){varfragment=document.createDocumentFragment(),file=document.createElement('input'),imgBox=document.createElement('div');file.type='file';file.accept=this.opt.accept||'*';file.className='xj-file';imgBox.className='xj-pre-img';//插入fragmentfragment.appendChild(file);fragment.appendChild(imgBox);//给包装组设置classthis.opt.el.className=this.opt.clsName;this.opt.el.appendChild(片段);}xjFile.prototype.watch=function(){vaript=this.opt.el.querySelector('.xj-file');var_this=this;ipt.addEventListener('change',(e)=>{varfile=ipt.files[0];//给组件赋值_this.value=file;varfileReader=newFileReader();//读取文件开始时触发.abort();_this.opt.beforeUpload(file,e);console.error('文件格式错误',file.type.toLowerCase());}}//读取完成触发的事件fileReader。onload=(e)=>{varimgBox=this.opt.el.querySelector('.xj-pre-img');if(isImage(file.type)){imgBox.innerHTML='';imgBox.style.backgroundImage='url('+fileReader.result+')';}else{imgBox.innerHTML=fileReader.result;}imgBox.title=file.name;this.opt.onLoad(e);}//文件读取错误事件fileReader.onerror=(e)=>{this.opt.onError(e);}//文件读取进度事件fileReader.onprogress=(e)=>{this.opt.onProgress(e);}isImage(file.type)?fileReader.readAsDataURL(文件):fileReader.readAsText(file);},false);}//清除ipt和components的值,支持链式调用xjFile.prototype.clearFile=function(){this.opt.el.querySelector('.xj-file').value='';this.value='';returnthis}//简单对象混合函数minix(source,target){for(varkeyintarget){source[key]=target[key];}returnsource}//检测图像类型函数isImage(type){varreg=/(image\/jpeg|image\/jpg|image\/gif|image\/png)/gi;returnreg.test(type)}//将方法挂载到windowwin.xjFile=xjFile;})(window,document);class版(后期规划)class版也很简单,大体框架如下,有兴趣的朋友可以实现一下~classXjFile{constructor(opt){}init(){}watch(){}render(){}clearFile(){}minix(source,target){}isImage(type){}}来总结一下,这个组件还是有待完善的。在以后的使用中,会慢慢更新,优化,欢迎大家提出宝贵意见