• 浏览器渲染相关和http的一些相关知识


    用户看到页面实际上可以分为两个阶段:页面内容加载完成页面资源加载完成,分别对应于DOMContentLoadedLoad
    DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片等
    load事件触发时,页面上所有的DOM,样式表,脚本,图片都已加载完成  

    浏览器渲染的过程主要包括以下五步
    1、浏览器将获取的HTML文档解析成DOM树。
    2、处理CSS标记,构成层叠样式表模型CSSOM(CSS Object Model)。
    3、将DOM和CSSOM合并为渲染树(rendering tree),代表一系列将被渲染的对象。
    4、渲染树的每个元素包含的内容都是计算过的,它被称之为布局layout。浏览器使用一种流式处理的方法,只需要一次绘制操作就可以布局所有的元素。
    5、将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting。
    注意:以上五个步骤并不一定一次性顺序完成,比如DOM或CSSOM被修改时,亦或是哪个过程会重复执行,这样才能计算出哪些像素需要在屏幕上进行重新渲染。
    而在实际情况中,JavaScript和CSS的某些操作往往会多次修改DOM或者CSSOM

     重绘(repaint):屏幕的一部分要重绘。渲染树节点发生改变,但不影响该节点在页面当中的空间位置及大小。

    譬如某个div标签节点的背景颜色、字体颜色等等发生改变,但是该div标签节点的宽、高、内外边距并不发生变化,此时触发浏览器重绘(repaint)。
    重排(reflow)【回流又称为重排】:当渲染树节点发生改变,影响了节点的几何属性(如宽、高、内边距、外边距、或是float、position、display:none;等等),导致节点位置发生变化,此时触发浏览器重排(reflow),需要重新生成渲染树。
    譬如JS为某个p标签节点添加新的样式:"display:none;"。导致该p标签被隐藏起来,该p标签之后的所有节点位置都会发生改变。此时浏览器需要重新生成渲染树,重新布局,即重排(reflow)。

    重排和重绘的必然关系
    注意:重排必将引起重绘,而重绘不一定会引起重排。

    什么情况下会引起重排
    当页面布局和几何属性改变时就需要重排;如下
    1、添加或者删除可见的DOM元素;
    2、元素位置改变——display、float、position、overflow等等;
    3、元素尺寸改变——边距、填充、边框、宽度和高度
    4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
    5、页面渲染初始化;
    6、浏览器窗口尺寸改变——resize事件发生时;

    如何减少和避免重排
    Reflow 的成本比 Repaint 的成本高得多的多。一个节点的 Reflow 很有可能导致子节点,甚至父节点以及兄弟节点的 Reflow 。
    在一些高性能的电脑上也许还没什么,但是如果 Reflow 发生在手机上,那么这个过程是延慢加载和耗电的。
    1、直接改变className,如果动态改变样式,则使用cssText(考虑没有优化的浏览器);
    2、让要操作的元素进行”离线处理”,处理完后一起更新;
    a) 使用DocumentFragment进行缓存操作,引发一次回流和重绘;
    b) 使用display:none技术,只引发两次回流和重绘;
    c) 使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;
    3、不要经常访问会引起浏览器flush队列的属性,如果你确实要访问,利用缓存;
    4、让元素脱离动画流,减少回流的Render Tree的规模;

     浏览器工作流程:构建DOM -> 构建CSSOM -> 构建渲染树 -> 布局 -> 绘制

    渲染页面时常见的不良现象
    由于浏览器的渲染机制不同,在渲染页面时会出现两种常见的不良现象—-白屏问题和FOUS(无样式内容闪烁)
    FOUC:由于浏览器渲染机制(比如firefox),再CSS加载之前,先呈现了HTML,就会导致展示出无样式内容,然后样式突然呈现的现象;
    白屏:有些浏览器渲染机制(比如chrome)要先构建DOM树和CSSOM树,构建完成后再进行渲染,如果CSS部分放在HTML尾部,由于CSS未加载完成,浏览器迟迟未渲染,从而导致白屏;也可能是把js文件放在头部,脚本会阻塞后面内容的呈现,脚本会阻塞其后组件的下载,出现白屏问题。

    如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因
    解释:
    JavaScript的加载、解析与执行会阻塞DOM的构建,也就是说,在构建DOM时,HTML解析器若遇到了JavaScript,那么它会暂停构建DOM,将控制权移交给JavaScript引擎,等JavaScript引擎运行完毕,浏览器再从中断的地方恢复DOM构建;
    并不是说 script 标签必须放在底部,因为还可以给 script 标签添加 defer 或者 async 属性
    JS文件不只是阻塞DOM的构建,它会导致CSSOM也阻塞DOM的构建;

    在没有defer或者async的情况下,会立即执行脚本,所以通常建议把script放在body最后
    <script src="script.js"></script>
    有async的话,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。
    但是多个js文件的加载顺序不会按照书写顺序进行
    <script async src="script.js"></script>
    有derer【延迟加载】的话,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成,并且多个defer会按照顺序进行加载
    <script defer src="script.js"></script>
    区别主要在于一个执行时间,defer会在文档解析完之后执行,并且多个defer会按照顺序执行,而async则是在js加载好之后就会执行,并且多个async,哪个加载好就执行哪个

    蓝色线代表网络读取,
    红色线代表执行时间,这俩都是针对脚本的
    绿色线代表 HTML 解析

    常见的http状态码相关:

    200 表示成功
    301 302 重定向
    304 从浏览器缓存加载
    401 用户没有访问权限
    403 权限不够,拒绝访问
    404 资源未找到
    500 服务器内部错误

    常见的 Content-Type 类型

    针对axios讲
    1、application/json是Axios默认的Content-Type --->Request Payload

    2、Content-Type: application/x-www-form-urlencoded --->Form Data 原始表单
    入参处理 data: qs.stringify(data) 一旦使用qs库的方法,就应该注意不能对请求体中的数据使用扩展运算符(...)
    另外一种处理方法
    let data = new URLSearchParams();
    data.append('key1', 'value1');
    data.append('key2', 'value2');

    3、Content-Type: multipart/form-data --->Form Data
    一般用来上传文件,指定传输数据为二进制数据,例如图片、mp3、文件等
    let data = new FormData();
    data.append('fileName', document.querySelector('input[type=file]').files[0]);
    data.append('key1', 'value1');
    data.append('key2', 'value2');

    通常的
    最常见的 POST 提交数据的方式,原生Form表单key1=val1&key2=val2 的方式进行编码 比如axios的 Qs.stringify(data)
    1、application/x-www-form-urlencoded (如?type=aa&bb)

    主体是序列化后的 JSON 字符串
    2、application/json (如:{age:20,sex:'男'})

    当上传的字段是文件时,会有Content-Type来说明文件类型;Content-disposition

    3、multipart/form-data (如:文件提交)

    既可以上传键值对,也可以上传文件,甚至多个文件,传输和存储数据,它非常适合万维网传输

    4、text/xml

    二进制文件类型。如application/pdf application/octet-stream
    5、binary (application/octet-stream)

    关于URL的几个重要概念
    一个完整的URL包括协议【http/https】、服务器地址(主机)【www.xxx.com/cn】、端口【8080】、路径【/xx】;
    例子:http://www.baidu.com:8080/user/search.html?a=1&b=2#results
    hash:URL的锚部分,包括开头的哈希(#)号,例如:"#results"。
    host:URL的主机端口部分,例如:"http://www.baidu.com:8080";
    hostname:URL的主机名部分,例如:"http://www.baidu.com";
    href:文档的URL的完整文本,不同于其他的指定URL的一部分Location属性。将这个属性设置为一个新的URL将导致浏览器读取并显示心得URL内容。把这个值直接赋值给Location对象将设置这个属性,把一个Location对象用作一个字符串将使用这个属性的值。
    pathname:URL的路径名部分,例如"/user/search.html";
    port:URL的端口部分,例如"8080";
    protocol:URL协议部分,包括尾部的冒号,例如"http:";
    search:URL的查询部分,包括开头的问号,例如"?a=1&b=2"。

    输入url到页面完成发生了什么
    (1)DNS解析:将域名解析为ip地址
    (2)建立TCP连接: 客户端浏览器与WEB服务器建立TCP(传输控制协议)连接,三次握手【浏览器-->服务器,服务器-->浏览器,浏览器-->服务器】
    (3)发送请求:请求报文 http协议的通信内容
    (4)响应请求:响应报文
    (5)渲染页面:dom树、css树、合并渲染树计算布局 绘制;
    (6)断开连接【非持久性】: TCP四次挥手。【浏览器-->服务器,服务器-->浏览器,服务器-->浏览器,浏览器-->服务器】
    http对应于应用层,Tcp协议对应于传输层,http协议是在Tcp协议之上建立的;

    浏览器内核
    1、webkit(v8引擎):chrome opera safari 国产浏览器和手机端
    2、gecko: firefox(火狐浏览器)
    3、trident: IE浏览器(IE的最新版本是edge)

    页面的渲染过程
    第一步:在CPU开辟一块栈内存,并分配一个主线程,基于进栈出栈的方式自上而下的解析代码
    第二步:第一次加载页面时,代码首先渲染出所有的DOM结构,当CSS资源请求回来后生成样式树,最后把DOM树和样式树混合在一起生成渲染树
    第三步:通知GPU(显卡)绘制出来即可

    为啥会出现浏览器兼容
    (1)部分浏览器会提前开发一些更好的功能,后期这些功能会被收录到W3C规范中,但在收录之前会存在一定的兼容性
    (2)各个浏览器厂商为了突出自己的独特性,用其他方法实现了W3C规范中的功能

    内容有点多!耐心看完希望会有收获~自己总结常用知识点储备~如有不对请指明;转载注明出处~

  • 相关阅读:
    DOM
    JavaScript 数组的方法总结
    vuex 状态持久化插件 —— vuex-persistedstate
    移动端1px细线
    CSS多行文本并显示省略号
    Java面试题
    Git提交分支
    Redis的安装配置
    Spring IoC
    单例模式
  • 原文地址:https://www.cnblogs.com/lhl66/p/13945548.html
Copyright © 2020-2023  润新知