不懂DOM渲染机制,确定能写出优质代码?

本文探讨了为何理解浏览器渲染机制对于前端开发者至关重要,详细介绍了DOM的加载过程、浏览器渲染流程,包括回流和重绘的影响。通过实例讲解了高性能的JavaScript DOM编程技巧,如减少DOM操作、优化CSS样式修改,以及资源压缩与合并等,旨在帮助开发者优化前端性能。


前言: 为什么要明白浏览器渲染机制

  • 知道浏览器的加载,可以在引用外部样式文件,JS时,可以放在合适的位置,最快加载完毕。
  • 明白浏览器如何进行解析,可以在构建DOM结构,组织CSS选择器的时候,以最优的写法,提高浏览器的解析速率。
  • 了解浏览器如何进行渲染及渲染的过程,可在编写JS时,可以减少“重绘”,“重新布局”的消耗。

一、几种DOM的认识

1 DOM是什么

  • DOM:Document Object Model,浏览器将HTML解析成树形的数据结构,简称DOM。
  • CSSOM:CSS Object Model,浏览器将CSS解析成树形的数据结构,简称CSSOM。
  • Render Tree: DOM和CSSOM合并后生成Render Tree,如下图:
    在这里插入图片描述
  • Layout: 计算出Render Tree每个节点的具体位置。
  • Painting:通过显卡,将Layout后的节点内容分别呈现到屏幕上.

2 加载过程

  • 浏览器获取html文件后,会自上而下的加载,并进行解析和渲染.
  • 加载就是获取文件的过程,遇到css和img则会发送异步请求,该请求不会影响HTML文件的加载.
  • 如果遇到Javascript文件,HTML文件会挂起渲染的进程,等Js文件加载完毕后,再继续进行渲染。
  • JavaScript可能会修改DOM,所以必须等待,否则可能导致后续HTML资源加载的浪费.
  • js文件加载完毕后,HTML才会再继续渲染,这也是将js文件写在底部原因。ES6中async和await可实现js的异步加载.

二、浏览器渲染流程

1.浏览器的请求渲染过程

在这里插入图片描述

  1. 当用户输入URL时,浏览器就会向服务器发送请求.
  2. 收到服务器响应内容后,浏览器的HTML解析器,会将HTML文件解析成DOM树,DOM树的构建是深度遍历的过程,当前节点的子节点都构建完成后,才会去构建当前节点的下一个兄弟节点。
  3. 将CSS解析成CSSOM树(CSS Rule Tree)
  4. 根据DOM树和CSSOM树,来构建Render Tree(渲染树),其并不等于DOM树,像hidden或display:none的东西,就没必要放在渲染树中了。
  5. Render Tree告诉浏览器网页中有哪些节点,以及节点的CSS定义和它们的从属关系,下一步操作就是Layout,就是计算出每个节点在屏幕中的位置。
  6. Layout后,浏览器已经知道哪些节点要显示,及节点的CSS属性是什么,每个节点在屏幕中的位置是哪里,就进入了最后一步painting,按照算出来的规则,通过显卡,把内容画到屏幕上。

2 回流和重绘,影响页面渲染速率

  1. 回流(reflow)

当浏览器发现页面某个部分发生了变化影响了布局,需要倒回去重新渲染,该过程称为回流。

  1. 重绘(repaint)

如果只是改变了某个元素的边框颜色、字体颜色、背景色等不影响它周围或内部布局的属性,将只会影响浏览器的重绘。

  1. 变化
  • 当元素的几何属性(宽或高)发生变化,浏览器需要重新计算元素的几何属性,同时其他元素的几何属性和位置也会受到影响。
  • 浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树,这个过程称为重排。完成重排后,浏览器会重新绘制受到影响的部分到屏幕,这个过程称为重绘。

三、高性能Javascript DOM编程

1 这里好有一比

用js进行DOM操作的代价很昂贵,所以要尽量少的用js操作DOM.

  • 把DOM和ECMAScript各自想象为一个岛屿,它们之间用收费桥梁链接,ECMAScript每次访问DOM,都要经过这座桥,并交纳“过桥费”,访问DOM的次数越多,费用也就越高。
  • 因此,推荐的做法是尽量减少过桥的次数,努力呆在ECMAScript岛上。那么怎样才能少出岛,实现高效呢?

2 DOM的访问与修改

获取DOM元素是有代价的,修改元素就更昂贵,因为它会导致浏览器重新计算页面的几何变化(重排和重绘)。

  • 如下,每一次遍历都要访问DOM两次,一次读取innerHTML的值,另一次重新赋值.
// html
  <div id="app">

  </div>
// js

    console.time('time');

    for (var i = 0; i < 16000; i++) {
      
      document.getElementById('app').innerHTML += 'a';

    }
    console.timeEnd('time'); // time1: 1080.73193359375 ms
    
  • 换一种写法,只访问操作DOM两次,一次读取页面内容,另一次赋值
    console.time('time');
    var str = '';
    for (var i = 0; i < 16000; i++) {

      str += 'a';

    }
    document.getElementById('app').innerHTML += str;
    console.timeEnd('time');  // time1: 1.8515625 ms

事实证明,一样的效果,越少访问DOM,其运行速度就越快.故要尽量的在js中处理完所有的效果,在一次性将结果设置到DOM上.

  • 当需要很多的插入操作和改动,使用下面的代码会很有问题
  var ul = document.getElementById("ul");
  for (var i = 0;i < 20;i++){
    var li = document.creatElement("li");
    ul.appendChild(li);
  }

每一次对文档的插入都会引起重新渲染(计算元素的尺寸、显示背景、内容等),故进行多次插入操作使得浏览器发生多次渲染,效率比较低。
这是我们提倡减少页面的渲染来提高DOM操作的效率的原因。

  • 最小化重排和重绘

改变元素多种样式的时候,最好用className,一次性完成操作,这样只会修改一次DOM。

3 一些优化

  • 设置DOM元素的display属性为none再操作该元素,这样浏览器会忽略它.
  var myElement = document.getElementById('myElement');
  myElement.style.display = 'none';
  
  //一些基于myElement的大量DOM操作

  myElement.style.display = 'block';
  • 复制DOM元素到内存中再对其进行操作
  var old = document.getElementById('myElement');
  var clone = old.cloneNode(true);

  //一些基于clone的大量操作
  old.parentNode.replaceChild(clone,old);
  • 用局部变量缓存样式信息从而避免频繁获取DOM数据

访问元素的offsetHeight属性,浏览器需要重新计算(重新布局),然后才能返回最新的值,如果这操作发生在循环中,那么浏览器要进行多次布局,严重浪费性能.
我们可以将其,直接读出来,保存在变量中

  //一般用法
  for (let i = 0;i < eleObj.length;i++) {
    eleObj[i].style.width = box.offsetHeight+ 'px';
  }

  //优化性能的用法
  let width = box.offsetWidth;
  for (let i = 0;i < eleObj.length;i++){
     eleObj[i].style.width = width + 'px';
  }

  • 资源压缩与合并。

文件合并:将多个js/css小文件合并为一个文件,减少网络请求次数。
css压缩与js的压缩比html压缩作用更大,同时css代码和js代码比html代码多的多。所以,css与js代码压缩非常有必要!

四 终极杀招

使用template模板,可以解决所有的问题,这也是vue的做法!
详情参考.

总结

  1. DOM和JS是两个孤岛,尽量少的使用JS操作DOM,操作的越多性能消耗越多.
  2. 只有元素的几何属性别修改,就会引起回流或者重绘,消耗DOM性能.
  3. 可以将所有关于DOM的操作,放在一起.直到有最终的效果,才去添加到页面中.
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值