整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Web页面中进度条的实现-Progressbar.j

Web页面中进度条的实现-Progressbar.js

使用ProgressBar.js,可以轻松地为Web创建响应式和时尚的进度栏。即使在移动设备上动画效果也表现良好。它提供了一些内置形状,如“直线”,“圆”和“半圆”,但是你也可以使用任何矢量图形编辑器创建自定义形状的进度条。ProgressBar.js是轻量级的,MIT开源许可,并支持包括IE9 +在内的所有主要浏览器。



Github


https://github.com/kimmobrunfeldt/progressbar.js

用法

以下是最简单的一个实例,从0大100%的进度条显示

<div></div>
var ProgressBar=require('progressbar.js');


// HTML
var bar=new ProgressBar.Line('#container', {easing: 'easeInOut'});
bar.animate(1); // Value from 0.0 to 1.0

以下是线、圆、半圆以及自定义形状的效果图,可以直接到文档查看动态的效果




安装

bower install progressbar.js

//or

npm install progressbar.js
  • CommonJS
var ProgressBar=require('progressbar.js')
var line=new ProgressBar.Line('#container');
  1. AMD
require.config({
 paths: {'progressbar': '../bower_components/progressbar.js/dist/progressbar'}
});

define(['progressbar'], function(ProgressBar) {
 var line=new ProgressBar.Line('#container');
});
  • Global variable
// If you aren't using any module loader, progressbar.js exposes
// global variable: window.ProgressBar
var line=new ProgressBar.Line('#container');
var circle=new ProgressBar.Circle('#example-percent-container', {
 color: '#FCB03C',
 strokeWidth: 3,
 trailWidth: 1,
 text: {
 value: '0'
 }
});

React组件

https://github.com/kimmobrunfeldt/react-progressbar.js

总结

在常见的Web开发中经常看到有些地方需要进度条显示或者类似的需求,如果你的项目并不是很庞大,但有些时候又不需要一些第三方框架的时候就可以使用这些独立的库来完成你想要的功能!



在前面

今年国庆假期终于可以憋在家里了不用出门了,不用出去看后脑了,真的是一种享受。这么好的光阴怎么浪费,睡觉、吃饭、打豆豆这怎么可能(耍多了也烦),完全不符合我们程序员的作风,赶紧起来把文章写完。

这篇文章比较基础,在国庆期间的业余时间写的,这几天又完善了下,力求把更多的前端所涉及到的关于文件上传的各种场景和应用都涵盖了,若有疏漏和问题还请留言斧正和补充。

自测读不读

以下是本文所涉及到的知识点,break or continue ?

  • 文件上传原理
  • 最原始的文件上传
  • 使用 koa2 作为服务端写一个文件上传接口
  • 单文件上传和上传进度
  • 多文件上传和上传进度
  • 拖拽上传
  • 剪贴板上传
  • 大文件上传之分片上传
  • 大文件上传之断点续传
  • node 端文件上传

原理概述

原理很简单,就是根据 http 协议的规范和定义,完成请求消息体的封装和消息体的解析,然后将二进制内容保存到文件。

我们都知道如果要上传一个文件,需要把 form 标签的enctype设置为multipart/form-data,同时method必须为post方法。

那么multipart/form-data表示什么呢?

multipart互联网上的混合资源,就是资源由多种元素组成,form-data表示可以使用HTML Forms 和 POST 方法上传文件,具体的定义可以参考RFC 7578。

multipart/form-data 结构

看下 http 请求的消息体



  • 请求头:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次请求要上传文件,其中boundary表示分隔符,如果要上传多个表单项,就要使用boundary分割,每个表单项由———XXX开始,以———XXX结尾。

  • 消息体- Form Data 部分

每一个表单项又由Content-Type和Content-Disposition组成。

Content-Disposition: form-data 为固定值,表示一个表单元素,name 表示表单元素的 名称,回车换行后面就是name的值,如果是上传文件就是文件的二进制内容。

Content-Type:表示当前的内容的 MIME 类型,是图片还是文本还是二进制数据。

解析

客户端发送请求到服务器后,服务器会收到请求的消息体,然后对消息体进行解析,解析出哪是普通表单哪些是附件。

可能大家马上能想到通过正则或者字符串处理分割出内容,不过这样是行不通的,二进制buffer转化为string,对字符串进行截取后,其索引和字符串是不一致的,所以结果就不会正确,除非上传的就是字符串。

不过一般情况下不需要自行解析,目前已经有很成熟的三方库可以使用。

至于如何解析,这个也会占用很大篇幅,后面的文章在详细说。

最原始的文件上传

使用 form 表单上传文件

在 ie时代,如果实现一个无刷新的文件上传那可是费老劲了,大部分都是用 iframe 来实现局部刷新或者使用 flash 插件来搞定,在那个时代 ie 就是最好用的浏览器(别无选择)。

DEMO



这种方式上传文件,不需要 js ,而且没有兼容问题,所有浏览器都支持,就是体验很差,导致页面刷新,页面其他数据丢失。

HTML

 <form method="post" action="http://localhost:8100" enctype="multipart/form-data">

        选择文件:
            <input type="file" name="f1"/> input 必须设置 name 属性,否则数据无法发送<br/>
<br/>
            标题:<input type="text" name="title"/><br/><br/><br/>

        <button type="submit" id="btn-0">上 传</button>

</form>

复制代码

文件上传接口

服务端文件的保存基于现有的库koa-body结合 koa2实现服务端文件的保存和数据的返回。

在项目开发中,文件上传本身和业务无关,代码基本上都可通用。

在这里我们使用koa-body库来实现解析和文件的保存。

koa-body 会自动保存文件到系统临时目录下,也可以指定保存的文件路径。



然后在后续中间件内得到已保存的文件的信息,再做二次处理。

  • ctx.request.files.f1 得到文件信息,f1为input file 标签的 name
  • 获得文件的扩展名,重命名文件

NODE

/**
 * 服务入口
 */
var http=require('http');
var koaStatic=require('koa-static');
var path=require('path');
var koaBody=require('koa-body');//文件保存库
var fs=require('fs');
var Koa=require('koa2');

var app=new Koa();
var port=process.env.PORT || '8100';

var uploadHost=`http://localhost:${port}/uploads/`;

app.use(koaBody({
    formidable: {
        //设置文件的默认保存目录,不设置则保存在系统临时目录下  os
        uploadDir: path.resolve(__dirname, '../static/uploads')
    },
    multipart: true // 开启文件上传,默认是关闭
}));

//开启静态文件访问
app.use(koaStatic(
    path.resolve(__dirname, '../static') 
));

//文件二次处理,修改名称
app.use((ctx)=> {
    var file=ctx.request.files.f1;//得道文件对象
    var path=file.path;
    var fname=file.name;//原文件名称
    var nextPath=path+fname;
    if(file.size>0 && path){
        //得到扩展名
        var extArr=fname.split('.');
        var ext=extArr[extArr.length-1];
        var nextPath=path+'.'+ext;
        //重命名文件
        fs.renameSync(path, nextPath);
    }
    //以 json 形式输出上传文件地址
    ctx.body=`{
        "fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
    }`;
});

/**
 * http server
 */
var server=http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ......   ');
复制代码

CODE

https://github.com/Bigerfe/fe-learn-code/

段时间有很多同学通过不同渠道问我关于浏览器渲染的问题。今天,小郭在这里用简单的一张图概括出浏览器渲染的全过程。

废话不多说,直接上图


渲染流程图


  1. 渲染进程收到HTML 文档后,遍历文档节点并转换为能够读懂的DOM 树结构;
  2. 渲染引擎将 CSS 样式表转化为浏览器可以理解的styleSheets对象,每一个对象都包含CSS规则。根据CSS规则对象计算出 DOM 节点的样式;
  3. 创建渲染树,并计算元素的布局信息。布局阶段会从渲染树的根节点开始遍历,然后确定每个节点对象在页面上的确切大小与位置,布局阶段的输出是一个盒子模型,它会精确地捕获每个元素在屏幕内的确切位置与大小。对渲染树进行分层,并生成分层树。
  4. 为每个图层生成绘制列表,并将其提交到合成线程。合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。合成线程发送绘制图块命令DrawQuad给浏览器进程。
  5. 浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。

写到这里一定有很不少人好奇,为什么我们写页面时要把script标签放在页面最低部呢?

别着急,答案就在下面。

这就是前端小伙伴经常遇到的一个问题:渲染阻塞


当浏览器遇到一个 script 标记时,DOM 构建将暂停,直至脚本完成执行,然后继续构建DOM。每次去执行JavaScript脚本都会严重地阻塞DOM树的构建,如果JavaScript脚本还操作了CSSOM,而正好这个CSSOM还没有下载和构建,浏览器甚至会延迟脚本执行和构建DOM,直至完成其CSSOM的下载和构建。

所以,script 标签的位置很重要。实际使用时,可以遵循下面两个原则:

CSS 优先:引入顺序上,CSS 资源先于 JavaScript 资源;
JS置后:我们通常把JS代码放到页面底部,且JavaScript 应尽量少影响 DOM 的构建。


现在终于知道我们使用script的时候经常将它置于页面最底部的原因了。

另外,这一点也是经常在前端面试题中看到它的身影。

到这里浏览器渲染的全部流程已经讲述完毕,如果还有疑问可以在下方留言,大家一起讨论。

有任何前端问题可以私信我,想了解更多前端知识关注公众号“一郭鲜”,小郭等着你的到来