先介绍浏览器加载一个网页需要经历那些过程;我们只讨论页面解析流程,不考虑网络请求过程。
浏览器内核拿到html文件后,大致分为一下5个步骤:
1. 解析html元素,构建dom 树
2. 解析CSS,生成页面css规则树(Style Rules)
3. 将dom树 和 css规则树关联起来,生成render树
4. 布局(layout/ reflow),浏览器会为Render树上的每个节点确定在屏幕上的尺寸、位置
5. 绘制Render树,绘制页面像素信息到屏幕上,这个过程叫paint
当你用原生js 或jquery等库去操作DOM时,浏览器会从构建DOM树开始讲整个流程执行一遍,所以频繁操作DOM会引起不需要的计算,导致页面卡顿,影响用户体验。而Virtual DOM能很好的解决这个问题。它用javascript对象表示virtual node(VNode),根据VNode 计算出真实DOM需要做的最小变动,然后再操作真实DOM节点,提高渲染效率。
2. Virtual DOM
虚拟DOM用javascript对象来表示VNode,VNode的结构如下:
虚拟节点(vNode)结构
下面是虚拟DOM的算法流程图:
虚拟DOM算法流程图
React Diff算法
高效的diff算法能够保证进行对实际的DOM进行最小的变动。但是 标准的的 Diff 算法 复杂度需要 O(n^3),这显然无法满足性能要求。要达到每次界面都可以整体刷新界面的目的,势必需要对算法进行优化。React里结合 Web 界面的特点做出了两个简单的假设,使得 Diff 算法复杂度直接降低到 O(n)。
1. 两个相同组件产生类似的 DOM 结构,不同的组件产生不同的 DOM 结构;
2. 对于同一层次的一组子节点,它们可以通过唯一的 id 进行区分。
算法上的优化是 React 整个界面 Render 的基础,保证了整体界面渲染的性能。
不同节点类型的比较
为了在树之间进行比较,我们首先要能够比较两个节点,在 React 中即比较两个虚拟 DOM 节点,当两个节点不同时,应该如何处理。这分为两种情况:(1)节点类型不同 ,(2)节点类型相同,但是属性不同。
节点类型不同:直接删除原节点, 插入新节点。
React 的 DOM Diff 算法实际上只会对树进行逐层比较,两棵树只会对同一层次的节点进行比较如下所述。
dom树
React 只会对相同颜色方框内的 DOM 节点进行比较,即同一个父节点下的所有子节点。当发现节点已经不存在,则该节点及其子节点会被完全删除掉,不会用于进一步的比较。这样只需要对树进行一次遍历,便能完成整个 DOM 树的比较。
相同类型节点的比较
React 会对属性进行重设从而实现节点的转换。
一、Css书写顺序:
1.位置属性(position, top, right, z-index, display, float等)
2.大小(width, height, padding, margin)
3.文字系列(font, line-height, letter-spacing, color- text-align等)
4.背景(background, border等)
5.其他(animation, transition等)
二、Css语法:
命名一般为小写英文字母。
为了代码的易读性,在每个声明块的左花括号前添加一个空格。
每条声明语句的 : 后应该插入一个空格。
所有声明语句都应当以分号结尾。最后一条声明语句后面的分号是可选的,但是,如果省略这个分号,你的代码可能更易出错。
对于属性值或颜色参数,省略小于 1 的小数前面的 0 (例如,.5 代替 0.5;-.5px 代替 -0.5px)。
十六进制值应该全部小写,例如,#fff。
尽量使用简写形式的十六进制值,例如,用 #fff 代替 #ffffff。
避免为 0 值指定单位,例如,用 margin: 0 代替 margin: 0px。
Css常用的一些命名:
可参考:CSS 常用命名 - 彼岸时光 - 博客园。
三、Css的引入:
Css的引入一般有两种,link和@import,一般建议使用link引入。这样可以避免考虑@import的语法规则和注意事项,避免产生资源文件下载顺序混乱和http请求过多的烦恼。
四、Css的命名规范(BEM,OOCSS):
什么是BEM:BEM的意思就是块(block)、元素(element)、修饰符(modifier),是由Yandex团队提出的一种前端命名方法论。这种巧妙的命名方法让你的CSS类对其他开发者来说更加透明而且更有意义。
命名约定如下:
.block{} // 块即是通常所说的 Web 应用开发中的组件或模块。每个块在逻辑上和功能上都是相互独立的。
.block__element{} // 元素是块中的组成部分。元素不能离开块来使用。BEM 不推荐在元素中嵌套其他元素。
.block--modifier{} // 修饰符用来定义块或元素的外观和行为。同样的块在应用不同的修饰符之后,会有不同的外观。
优点:
BEM 的优点在于所产生的 CSS 类名都只使用一个类别选择器,可以避免传统做法中由于多个类别选择器嵌套带来的复杂的属性级联问题。在 BEM 命名规则中,所有的 CSS 样式规则都只用一个类别选择器。因此所有样式规则的特异性(specificity)都是相同的,也就不存在复杂的优先级问题。这可以简化属性值的层叠规则。代码清单中的命名规则的好处在于每个 CSS 类名都很简单明了,而且类名的层次关系可以与 DOM 节点的树型结构相对应。
缺点:
这样类名过于长,且复杂。
什么是OOCSS(面向对象CSS):
OOCSS 表示的是面向对象 CSS(Object Oriented CSS),是一种把面向对象方法学应用到 CSS 代码组织和管理中的实践。 OOCSS最关键的一点就是:提高他的灵活性和可重用性。这个也是OOCSS最重要的一点。OOCSS主张是通过在基础组件中添加更多的类,从而扩展基础组件的CSS规则,从而使CSS有更好的扩展性。
OOCSS的优点:
减少CSS代码。
具有清洁的HTML标记,有语义的类名,逻辑性强的层次关系。
语义标记,有助于SEO。
更好的页面优化,更快的加载时间(因为有很多组件重用)。
可扩展的标记和CSS样式,有更多的组件可以放到库中,而不影响其他的组件。
能轻松构造新的页面布局,或制作新的页面风格。
OOCSS的缺点:
OOCSS适合真正的大型网站开发,因为大型网站用到的可重用性组件特别的多,如果运用在小型项目中可能见不到什么成效。所以用不用OOCSS应该根据你的项目来决定。如果没用巧妙的使用,创建组件可能对于你来说是一堆没用的东西,成为一烂摊子,给你的维护带来意想不到的杯具,说不定还是个维护的噩梦。
欢迎到优就业来了解
1、 域名解析
2、 根据IP建立TCP连接(三次握手)
3、 发送HTTP请求
4、 服务器处理请求并返回HTTP报文
5、 浏览器解析并渲染页面
6、 连接结束,关闭TCP连接(四次挥手)
当输入一个域名的时候,我们首先要做的就是 将域名转化成IP地址 。前端的静态资源等,都是存储在服务器上。在计算机网络中,我们不能通过域名直接访问,只能通过IP地址访问到具体的主机。
1、首先 浏览器会查询自身的缓存 中,有没有此条域名的解析,如果有的话,就返回这个解析后的地址。
2、如果浏览器自身的缓存中,没有找到与此条域名对应的IP地址,那么就会去 操作系统中的缓存 中查找是否有这条域名的解析。
3、如果在操作系统中也没有找到的话,那么就需要通过 DNS(域名系统) 帮助我们解析。
4、DNS域名解析过程(详细看参考链接)
浏览器与远程web服务器通过TCP三次握手协商来建立一个TCP/IP连接。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
一旦TCP/IP连接建立,浏览器会通过该连接向远程服务器发送HTTP请求。
当浏览器再次访问某个url时,会先获取资源的header信息, 判断是否命中强缓存 :
1、如命中,直接从缓存获取资源,包括响应的header信息( 请求不会和服务器通信 ),也就是强缓存
2、如未命中强缓存,浏览器发送请求到服务器,该请求会携带第一次请求返回的有关缓存的header信息,由服务器根据请求种的相关header信息来 对比结果是否协商缓存命中
1)若命中,服务器 返回新的响应header信息,更新缓存中对应的header信息,但并不返回资源内容 ,它会告诉浏览器可以直接从缓存获取
2)否则,返回最新的资源内容
Expires :Expires 的值是一个 绝对时间的GMT格式的时间字符串(如Thu, 02 Sep 2021 11:03:45 GMT) ,在浏览器发起请求的时候,会根据系统时间和 Expires 的值进行比较,如果发送请求的时间在expires之前,那么本地缓存始终有效,否则就会发送请求到服务端来获取资源。
注:这个字段会导致一个问题,要是系统时间与服务器时间不一致的时候,就可能出现假性失效,或者出现缓存已经失效了,但是并未去请求最新资源
Cache-control :HTTP/1.1 中新增的属性,属性值具有以下几个:
pragma :不使用强缓存,需要验证缓存是否新鲜。(HTTP/1.1 之前版本的历史遗留字段,仅作为与 HTTP/1.0 的向后兼容而定义)
协商缓存都是由浏览器和服务器协商,来确定是否缓存,主要通过两组header字段,两组字段都是 成对出现 的,即第一次请求的响应头上带某个字段(Last-Modified 或 Etag),则后续请求会带上对应的请求字段(if-modified-since或者if-none-match),若响应头没有,则请求头也不会有对应的字段
①、解析 HTML,生成 DOM 树(浏览器不能直接理解和使用HTML,需要将HTML转换为浏览器能够理解的结构)
②、解析 CSS,生成 CSS 规则树
③、合并 CSS 和 DOM 树,生成render树
④、计算渲染树的布局(Layout/reflow),即各元素尺寸、位置的计算
⑤、绘制 render 树(paint),绘制页面像素信息
⑥、浏览器将各层信息发送给GPU,GPU将各层合成,显示在屏幕
注 :
1 、render树的节点并不等同的dom树的节点,因为有些节点的display为none,那么在生成render树的时候,就不会将其加入到render树中
2 、 当我们浏览器获得HTML文件后,会自上而下的加载,并在加载过程中进行解析和渲染。
3 、 如果在加载过程中遇到外部CSS文件和图片,浏览器会另外发送一个请求,去获取CSS文件和相应的图片,这个请求是异步的,并不会影响HTML文件的加载。 不会阻塞DOM树的解析,会阻塞DOM树的渲染和后面js语句的执行 ,当计算样式的时候需要等待css文件的资源进行层叠样式,资源阻塞了,会进行等待,直到网络超时,network报出错误,渲染进程继续层叠样式计算。为了避免让用户看到长时间的白屏时间,应该提高css的加载速度:
4 、如果遇到Javascript文件,HTML文件会挂起渲染的进程,等待JavaScript文件加载完毕后,再继续进行渲染。因为JavaScript可能会修改DOM,导致后续HTML资源白白加载,所以HTML必须等待JavaScript文件加载完毕后,再继续渲染,这也就是为什么JavaScript文件在写在底部body标签前的原因
5 、 每个页面至少需要一次回流,就是在页面第一次加载的时候。
1.第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
2.第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
3.第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
4.第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1, Server进入CLOSED状态,完成四次挥手。
参考: 前端进阶必看——详细版输入URL到界面展示的过程
简述浏览器渲染机制