前端开发浏览器怎么渲染页面

web前端开发必备浏览器|标准的前端开发流程|开发前端模板引擎

基本概念
web 页面运行在各种各样的浏览器当中,浏览器载入、渲染页面的速度直接影响着用户体验简单地说,页面渲染就是浏览器将 html 代码根据 css 定义的规则显示在浏览器窗口中的这个过程。

渲染过程

  1. 用户输入网址(假设是个 html 页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回 html 文件;
  2. 浏览器开始载入 html 代码,发现 <head> 标签内有一个 <link> 标签引用外部 css 文件;
  3. 浏览器又发出 css 文件的请求,服务器返回这个 css 文件;
  4. 浏览器继续载入 HTML 中 <body> 部分的代码,并且 css 文件已经拿到手了,可以开始渲染页面了;
  5. 浏览器在代码中发现一个 <img> 标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码;
  6. 服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;
  7. 浏览器发现了一个包含一行 JavaScript 代码的 <script> 标签,赶快运行它;
  8. JavaScript 脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个 <div>(style.display=”none”)。杯具啊,突然就少了这么一个元素,浏览器不得不重新渲染这部分代码;
  9. 终于等到了 </html> 的到来,浏览器泪流满面……
  10. 等等,还没完,用户点了一下界面中的“换肤”按钮,JavaScript 让浏览器换了一下 <link> 标签的 css 路径;
  11. 浏览器召集了在座的各位 <div><span><ul><li> 们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的CSS文件,重新渲染页面。 浏览器每天就这么来来回回跑着,要知道不同的人写出来的 HTML 和 CSS 代码质量参差不齐,说不定哪天跑着跑着就挂掉了。好在这个世界还有这么一群人——页面重构工程师,平时挺不起眼,也就帮视觉设计师们切切图啊改改字,其实背地里还是干了不少实事的。

reflow(回流)
说到页面为什么会慢?那是因为浏览器要花时间、花精力去渲染,尤其是当它发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,内行称这个回退的过程叫 reflow(回流,相关链接:reflow(回流))。
reflow 几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显 示与隐藏)等,都将引起浏览器的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲 染。通常我们都无法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。 当 然,reflow 问题是可以优化的,我们可以尽量减少不必要的 reflow。比如开头的例子中的 <img> 图片载入问题,这其实就是一个可以避免的 reflow —— 给图片设置宽度和高度就可以了。这样浏览器就知道了图片的占位面积,在载入图片前就预留好了位置。

repaint(重绘)
另 外,有个和 reflow 看上去差不多的术语:repaint,中文叫重绘。如果只是改变某个元素的背景色、文 字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器 repaint。repaint 的速度明显快于 reflow(在IE下需要换一下说法,reflow 要比 repaint 更缓慢)。
重排
当页面上的改变影响了文档内容、结构或者元素定位时,就会发生重排(或称“重新布局”)。重排通常由以下改变触发:
• DOM 操作(如元素增、删、改或者改变元素顺序)。
• 内容的改变,包括 Form 表单中文字的变化。
• 计算或改变 CSS 属性。
• 增加或删除一个样式表。
• 改变”class”属性。
• 浏览器窗口的操作(改变大小、滚动窗口)。
• 激活伪类(如:hover状态)。

浏览器如何优化渲染?
浏览器尽最大努力限制重排的过程仅覆盖已更改的元素的区域。举个例子,一个 position 为 absolue 或 fixed 的元素的大小变化只影响它自身和子孙元素,而对一个 position 为 static 的元素做同样的操作就会引起所有它后面元素的重排。
另一个优化就是当运行一段Jjavascript 代码的时候,浏览器会将一些修改缓存起来,然后当代码执行的时候,一次性的将这些修改执行。

举例来说,这段代码会触发一次重绘和一次重排:

  1. var $body = $(‘body’);
  2. $body.css(‘padding’, ‘1px’); // 重排, 重绘
  3. $body.css(‘color’, ‘red’); // 重绘
  4. $body.css(‘margin’, ‘2px’); // 重排, 重绘
  5. // 实际上只有一次重排和重绘被执行。

如上面所说,访问一个元素的属性会进行一次强制重排。如果我们给上面的代码加上一行读取元素属性的代码,这个情况就会出现:

  1. var $body = $(‘body’);
  2. $body.css(‘padding’, ‘1px’);
  3. $body.css(‘padding’); // 这里读取了一次元素的属性,一次强制重排就会发生。
  4. $body.css(‘color’, ‘red’);
  5. $body.css(‘margin’, ‘2px’);

上面这段代码的结果就是,进行了两次重排。因此,为了提高性能,你应该讲读取元素属性的代码组织在一起(细节的例子可以看JSBin上的代码)。
有一种情况是必须触发一次强制重排的。例如:给元素改变同一个属性两次(比如margin-left),一开始设置100px,没有动画,然后通过动画的形式将值改为50px。具体可以看例子,当然,我在这里会讲更多的细节。
我们从一个有transition的CSS class开始:

  1. .has-transition {
  2. -webkit-transition: margin-left 1s ease-out;
  3. -moz-transition: margin-left 1s ease-out;
  4. -o-transition: margin-left 1s ease-out;
  5. transition: margin-left 1s ease-out;
  6. }

然后进行实现:

  1. //我们的元素默认有”has-transition”属性
  2. var $targetElem = $(‘#targetElemId’);
  3. //删除包含transition的class
  4. $targetElem.removeClass(‘has-transition’);
  5. // 当包含transition的class已经没了的时候,改变元素属性
  6. $targetElem.css(‘margin-left’, 100);
  7. // 再将包含transition的class添加回来
  8. $targetElem.addClass(‘has-transition’);
  9. // 改变元素属性
  10. $targetElem.css(‘margin-left’, 50);

上面的实现没有按照期望的运行。所有的修改都被浏览器缓存了,只在上面这段代码的最后才会执行。我们需要的是一次强制重排,我们可以通过进行以下修改来实现:

  1. //删除包含transition的class
  2. $(this).removeClass(‘has-transition’);
  3. // 改变元素属性
  4. $(this).css(‘margin-left’, 100);
  5. //触发一次强制重排,从而使变化了的class或属性能够立即执行。
  6. $(this)[0].offsetHeight; // offsetHeight仅仅是个例子,其他的属性也可以奏效。
  7. // 再将包含transition的class添加回来
  8. $(this).addClass(‘has-transition’);
  9. // 改变元素属性
  10. $(this).css(‘margin-left’, 50);

现在这段代码如我们所期望的运行了。

实际的优化建议
汇总了一些有用的信息,我建议以下几点:
• 创建合法的 HTML 和 CSS ,别忘了制定文件编码,Style 应该写在 head 标签中,script 标签应该加载 body 标签结束的位置。
• 试着简化和优化 CSS 选择器(这个优化点被大多数使用 CSS 预处理器的开发者忽略了)。将嵌套层数控制在最小。以下是 CSS 选择器的性能排行(从最快的开始):

  1. ID选择器:#id
  2. class选择器: .class
  3. 标签: div
  4. 相邻的兄弟元素:a + i
  5. 父元素选择器: ul > li
  6. 通配符选择器: *
  7. 伪类和伪元素: a:hover ,你应该记住浏览器处理选择器是从右向左的,这也就是为什么最右面的选择器会更快——#id或.class。
  8. div * {…} // bad
  9. .list li {…} // bad
  10. .list-item {…} // good
  11. list .list-item {…} // good
  12. 在你的脚本中,尽可能的减少 DOM 的操作。把所有东西都缓存起来,包括属性和对象(如果它可被重复使用)。进行复杂的操作的时候,最好操作一个“离线”的元素(“离线”元素的意思是与 DOM 对象分开、仅存在内存中的元素),然后将这个元素插入到 DOM 中。
  13. 如果你使用 jquery,遵循jquery 选择器最佳实践
  14. 要改变元素的样式,修改“class”属性是最高效的方式之一。你要改变 DOM 树的层次越深,这一条就越高效(这也有助于将表现和逻辑分开)。
  15. 尽可能的只对 position 为 absolute 或 fix 的元素做动画。
  16. 当滚动时禁用一些复杂的 :hover动画是一个很好的主意(例如,给 body 标签加一个 no-hover 的 class)关于这个主题的文章。

前端开发 模块化 规范|手机web前端开发框架|前端开发的主流框架有哪些

赞(0)
前端开发者 » 前端开发浏览器怎么渲染页面
64K

评论 抢沙发

评论前必须登录!