DOCTYPE
DOCTYPE 及 作用
DOCTYPE 是 document type(文档类型的)的简写 作用:
告诉浏览器需要通过哪一种规范(文档类型定义,DTD)解析文档(比如HTML或XHTML规范) DTD 告诉浏览器,我是什么文档类型。浏览器根据这个来判断用什么浏览引擎来解析它渲染它 DOCTYPE 就是直接告诉浏览器什么是 DTD。告诉浏览器包含哪个 DTD,也就是哪个文档类型
常见的 DOCTYPE 声明
<!-- HTML 5 -->
<!doctype html>
<!-- HTML 4.01 Strict -->
<!-- 这个 DTD 包含所有 HTML 元素和属性,但不包括展示性的和弃用的元素(比如 font) -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!-- HTML 4.01 Transitional -->
<!-- 这个 DTD 包含所有 HTML 元素和属性,包括展示性的和弃用的元素(比如 font) -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
面试注意:
一个 strict,一个 loose。不用记怎么写。 > 知道 4.01 有两个模式,一个严格模式,一个传统模式。 > 知道 HTML5 怎么写。能说出严格和宽松的区别。 > 如果严格模式,使用了弃用的元素,页面是是有问题的。宽松模式没有问题。
**
浏览器渲染过程
抛出一个老生常谈的面试问题:从输入 URL 到页面加载完成,发生了什么? 首先我们需要通过 DNS域名解析,将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛出我们的 HTTP 请求,服务端处理完我们的请求之后,把目标数据放在 HTTP 响应里返回给客户端,拿到响应数据的浏览器就可以开始走一个渲染的流程。渲染完毕,页面便呈现给了用户,并时刻等待响应用户的操作。
面试大白话解释:
输入 url,会有一个 dns 解析,然后发到服务器,服务器再响应,响应过来,到了客户端,浏览器这边就开始渲染过程
** 过程片段分为:
- DNS解析
- TCP连接
- HTTP请求
- service处理,HTTP响应返回
- 浏览器拿到数据,解析响应内容,展示数据内容
渲染过程很复杂,但是不会说的那么细。几句话说清就好了。
浏览器拿到 HTML 和 css 之后要干什么?
HTML 经过 HTML parser 转化成 DOM tree,css 按着 css 规则和 css 解释器,转成 CSSOM Tree,两棵树之间一整合,就是 attachment,形成一个 render tree,告诉浏览器渲染的树的结构就出来了。render tree 不包含 html 具体内容,也不知道具体位置是什么。比如有一个 div,layout 之前,不知道画在具体什么位置。这时候通过 layout 就可以精确计算到要显示的这些 dom 真正的宽高,位置颜色,最后开始 paint,画图,把内容呈现出来。最后 display,在浏览器上能看到页面效果。
CSSOM 树和 DOM 树连接在一起形成一个 render tree,渲染树用来计算可见元素的布局并且作为将像素渲染到屏幕上的过程的输入。
DOM 树和 CSSOM 树连接在一起形成 render tree .
render tree 只包含了用于渲染页面的节点布局计算了每一个对象的准确的位置以及大小绘画是最后一步,绘画要求利用 render tree 来将像素显示到屏幕上第一步是结合 DOM 树和 CSSOM 树形成“render tree”,渲染树用来描述所有可见的 DOM 内容,并且将 CSSOM 样式信息附加到节点上。
为了形成渲染树,浏览器大致做的事情有:从 DOM 树根节点开始,遍历每一个可见的节点一些节点是完全不可见的(比如 script 标签,meta 标签等),这些节点会被忽略,因为他们不会影响渲染的输出一些节点是通过 CSS 样式隐藏了,这些节点同样被忽略——例如上例中的 span 节点在 render tree 中被忽略,因为 span 样式是 display:none;对每一个可见的节点,找到合适的匹配的 CSSOM 规则,并且应用样式显示可见节点(节点包括内容和被计算的样式)
让我们快速的浏览下浏览器所做的事情:
处理 HTML 标签建立 DOM 树
处理 CSS 标签建立 CSSOM 树
连接 CSSOM 树和 DOM 树形成一个 render 树
在 render 树上运行布局来计算每个节点的形状
在屏幕上画每一个节点
虽然我们的页面很简单,但是它进行了大量的工作!
重绘与重排
重绘(repaint 或 redraw)
定义:当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上。重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。 这个过程称之为重绘。
触发重绘的条件:
- DOM 改动
- CSS 改动
重排(重构/回流/reflow)
定义:当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
触发 Reflow:
- 当你增加、删除、修改 DOM 节点时,会导致 Reflow 或 Repaint
- 当你移动 DOM 的位置,或是搞个动画的时候
- 当你修改 CSS 样式的时候
- 当你 Resize 窗口的时候(移动端没有这个问题),或者滚动的时候
- 当你修改网页的默认字体时
注意: table 及其内部元素可能需要多次计算才能确定好其在渲染树中节点的属性值,比同等元素要多花两倍时间,这就是我们尽量避免使用 table 布局页面的原因之一。
重绘和重排的关系
在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。所以,重排必定会引发重绘,但重绘不一定会引发重排。
如何尽量减小重绘?
重绘无法避免,但是最大程度减小。比如把用户输入计算条件,把输入隐藏掉,计算结果显示出来。两个交互,用户输入,然后输入隐藏,结果展示。这个过程,呈现内容不一样了。怎么做,少画一些东西。就是要把最后的结果,放在一个节点,就算有很多结果,也不要一个一个添加,而是放在一个片段里面,然后一次添加片段。也就是重绘一次。不然你加一个节点,重新重绘一次。 简单来说,能批量操作就批量操作。
Links
渲染树构建、布局及绘制:https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction