上个星期六和星期天两天分别参加了两个技术沙龙,第一天因为中午没有睡觉,那个下午整个人好像要倒下的感觉。基本上听到的东西也就是那几个讲到的标题。第二天为了不重蹈覆辙,上午上完课后,中午睡了一个多小时,才去听,颇有收获。不过真的知道了自己很多方面的知识都很缺陷。因为一直都是站在一个前端实现者的角度来看,但是对其它的相关的技术和大的技术发展形势都不闻不问,一个方面,是害怕,另一个方面感到自己真的好像井底之蛙。交流交流,要不断地学习,不断地进步才行。
废话不说了,还是开始记笔记吧,因为不断地学习和了解,到最后的整理的过程是一个很享受的过程。
两个技术沙龙都谈到了浏览器的原理,我想,浏览器的原理会是怎样的呢,所以开始了我在网上的阅读和整理的过程,下面是总结的几个部分。
1. 浏览器展示的东西:
只要是一个网民,那么他一定会对浏览器的基本展示的东西有所了解。1)主浏览窗口;2)主浏览窗口之外的部分,eg:“地址栏”,“前进”,“后退”,“刷新”,”历史记录“按钮等,这一些功能的出现,目的就是为了方便于我们浏览网页。
2. 浏览器的工作原理:
我想先把自己学过的计算机的知识调用出来方便于理解后面要讲到的”浏览器结构“。下面是在一个人的文章中找到的一张图:
下面附上我自己对这一张图的理解:
1). 有用户在地址栏输入某一个链接,点击确定,或在网页上点击到某一个链接。目的:访问网页;2). 浏览器开始向”网络服务器“发送http请求,网络服务器对请求进行处理,并且在适当的时候进入到数据存储层中取到数据。3). 数据返回到网络服务器,网络服务器再通过一系列的处理把”html内容“放到”response“这一个容器中,并最终返回到浏览器中。4). 浏览器开始解析”response“容器中的html内容,并创建DOM树。5).当遇到CSS外文件链接的时候,开始下载CSS,并把它应用到DOM树中,并构建render树。6). 当遇到javascript外文件链接的时候,解析并执行javascript..在第5和6的过程中浏览器渲染页面。
3. 浏览器的结构(下面图是从网上的一篇文章找到的经典图):
下面是对各个结构部分的详细解释(和上面那个图片来自同篇文章):
1). 用户界面(user interface):包括地址栏、后退/前进按钮、书签目录等,也就是你所看到的除了用来显示你所请求页面的主窗口之外的其他部分。
2). 浏览器引擎 - 用来查询及操作渲染引擎的接口。
3.) 渲染引擎 - 用来显示请求的内容,例如,如果请求内容为html,它负责解析html及css,并将解析后的结果显示出来。
4). 网络 - 用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作。
5). UI后端 - 用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口。
6). JS解释器 - 用来解释执行JS代码。
7). 数据存储 - 属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术
其中最主要的还是渲染引擎,正是有了渲染引擎,浏览器才给我们提供了可视化界面。
4. CSS的载入问题:
浏览器CSS匹配不是从左到右进行查找,而是从右到左进行查找。比如DIV#divBoxpspan.red{color:red;},浏览器的查找顺序如下:先查找html中所有class=’red’的span元素,找到后,再查找其父辈元素中是否有p元素,再判断p的父元素中是否有id为 divBox的div元素,如果都存在则CSS匹配上。
这是一个疑问:为什么要把CSS文件放在head中呢?
如果我们把CSS样式放在页面底部,虽然使页面内容能更快的加载(因为将加载css 文件的时间放在最后,从而使页面内容先显示出来),但这样的内容是没有样式的,在CSS文件加载进来后,浏览器再对DOM使用样式,会出现我们常说的“无样式之闪烁”。
5. JavaScript的载入问题:
不论js代码是内联还是包含在一个不相干的外部文件中,页面下载和解析过程肯定会停下,等待脚本执行完成这些处理,然后才能继续进行。——大多数浏览器使用单进程处理JavaScript的多个任务,同一时间只能有一个任务执行。
6. render树(渲染树或说是呈现树)的生成:
下面是这一幅图所在的文章所写的几段话,我觉得很容易理解:
1). 浏览器把获取到的html代码解析成1个Dom树,html中的每个tag都是Dom树中的1个节点,根节点就是我们常用的document对象(<html> tag)。dom树就是我们用firebug或者IE Developer Toolbar等工具看到的html结构,里面包含了所有的html tag,包括display:none隐藏,还有用JS动态添加的元素等。
2). 浏览器把所有样式(主要包括css和浏览器的样式设置)解析成样式结构体,在解析的过程中会去掉浏览器不能识别的样式,比如IE会去掉-moz开头的样式,而firefox会去掉_开头的样式。
3). dom tree和样式结构体结合后构建呈现树(render tree),render tree有点类似于dom tree,但其实区别有很大,render tree能识别样式,render tree中每个node都有自己的style,而且render tree不包含隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现,而且不会影响呈现的,所以就不会包含到render tree中。注意 visibility:hidden隐藏的元素还是会包含到render tree中的,因为visibility:hidden 会影响布局(layout),会占有空间。根据css2的标准,render tree中的每个节点都称为box(Box dimensions),box所有属性:width,height,margin,padding,left,top,border等。
即这一段话很好地把render tree之所以为呈现树/渲染树很好地体现出来。
7. 回流和重绘:
这两个词是今天才搞明白的,不过它们对于html,css,javascript的代码的优化起到了很至关重要的作用,所以想要做好前端代码的优化工作一定要好好地理解这两个词它们所拥有的含义。
1). repaint(重绘)是在一个元素的外观被改变,但没有改变布局的情况下发生。——如果只是改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器repaint。
2). reflow(回流):浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,这个回退的过程就叫回流。
8.好的文章
上面的总结都是基于下面这几个文章,如果以后有时间或有需要,都可以好好地回来看下面的几篇文章:
1. 前端必读:浏览器内部工作原理(详细,全面,入理):http://kb.cnblogs.com/page/129756/#chapter5
2. 通过浏览器渲染过程来进行前端优化:http://www.cnblogs.com/baochuan/archive/2012/05/29/2524694.html
3. 回流与重绘:CSS性能让JavaScript变慢?(讲的非常细,非常精彩):http://www.cnblogs.com/rhinemetal/archive/2012/06/29/2569517.html
4. 让网络更快一些——最小化浏览器中的回流(reflow):http://www.zhangxinxu.com/wordpress/?p=311
5. 高性能WEB开发(8) - 页面呈现、重绘、回流:http://www.blogjava.net/BearRui/archive/2010/05/10/web_performance_repaint_relow.html
上面的几篇文章没有很全面的把它们看完,不过了解了个大概,对浏览器的基本原理,回流和重绘在编码的时候需要注意到的问题也有了一些了解。