侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

教你3分钟利用原生js实现有进度监听的文件上传预览组件

前端  /  管理员 发布于 5年前   268

前言

本文主要介绍如何使用原生js,通过面向对象的方式实现一个文件上传预览的组件,该组件利用FileReader来实现文件在前端的解析,预览,读取进度等功能,并对外暴露相应api来实现用户自定义的需求,比如文件上传,进度监听,自定义样式,读取成功回调等。

组件设计架构如下:

涉及的核心知识点如下:

  1. 闭包:减少变量污染,缩短变量查找范围
  2. 自执行函数
  3. file API:对文件进行读取,解析,监控文件事件
  4. DocumentFragment API:主要用来优化dom操作
  5. minix :用来实现对象混合
  6. 正则表达式:匹配文件类型
  7. class :类组件

github地址

用原生js实现具有进度监听的文件上传预览组件 (本地下载)

Demo演示

使用:

css代码:

.xj-wrap {   position: relative;   display: inline-block;   border: 1px dashed #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%;   height: 100%;   background-repeat: no-repeat;   background-position: center center;   background-size: 100%;  }  .xj-file {   position: absolute;   left: 0;   right: 0;   bottom: 0;   top: 0;   opacity: 0;   cursor: pointer;  }

js代码:

(function(win, doc){ function xjFile(opt) {  var defaultOption = {   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) }  };  // 获取dom  if(opt.el) {   opt.el = typeof opt.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() {  var fragment = 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';  // 插入fragment  fragment.appendChild(file);  fragment.appendChild(imgBox);  // 给包裹组件设置class  this.opt.el.className = this.opt.clsName;  this.opt.el.appendChild(fragment); } xjFile.prototype.watch = function() {  var ipt = this.opt.el.querySelector('.xj-file');  var _this = this;  ipt.addEventListener('change', (e) => {   var file = ipt.files[0];   // 给组件赋值   _this.value = file;   var fileReader = new FileReader();   // 读取文件开始时触发   fileReader.onloadstart = function(e) {    if(_this.opt.accept !== '*' && _this.opt.accept.indexOf(file.type.toLowerCase()) === -1) {     fileReader.abort();     _this.opt.beforeUpload(file, e);     console.error('文件格式有误', file.type.toLowerCase());    }   }   // 读取完成触发的事件   fileReader.onload = (e) => {    var imgBox = 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(file) : fileReader.readAsText(file);     }, false); } // 清除ipt和组件的值,支持链式调用 xjFile.prototype.clearFile = function() {  this.opt.el.querySelector('.xj-file').value = '';  this.value = '';  return this } // 简单对象混合 function minix(source, target) {  for(var key in target) {   source[key] = target[key];  }  return source } // 检测图片类型 function isImage(type) {  var reg = /(image\/jpeg|image\/jpg|image\/gif|image\/png)/gi;  return reg.test(type) } // 将方法挂载到window上 win.xjFile = xjFile;})(window, document);

class版(后期规划)

class版的也很简单,大致框架如下,感兴趣的朋友可以实现一下呦~

class XjFile { constructor(opt) { } init() { } watch() { } render() { } clearFile() { } minix(source, target) {   } isImage(type) {   }}

总结

该组件仍有需要完善的地方,在后期使用中,会慢慢更新,优化,欢迎大家提出宝贵的建议。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家的支持。

您可能感兴趣的文章:

  • js 实现 input type="file" 文件上传示例代码
  • 简单实现js上传文件功能
  • JS中使用FormData上传文件、图片的方法
  • 客户端js判断文件类型和文件大小即限制上传大小
  • js获取上传文件的绝对路径实现方法
  • 原生JS和jQuery版实现文件上传功能
  • JS文件上传神器bootstrap fileinput详解
  • JS简单实现文件上传实例代码(无需插件)
  • js实现点击按钮弹出上传文件的窗口
  • js判断上传文件后缀名是否合法


  • 上一条:
    使用 node.js 模仿 Apache 小部分功能
    下一条:
    详解基于 Node.js 的轻量级云函数功能实现
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客