• 前端页面卡顿-代码优化


      原文地址--->http://developer.51cto.com/art/201504/473422.htm

      最近做项目时遇到了页面加载卡顿问题,一时没有头绪,感到无从下手,看到这篇文章,所以整体梳理了一下,在此记录。

    在富客户端网页应用中,界面上的UI的更改是通过DOM操作实现的。

        尽管DOM提供了丰富接口供外部调用,但是dom操作的代价很高,

    页面前端代码的性能瓶颈大多集中在DOM操作上,因此,前端性能优化的

    一个主要的关注点是dom操作的优化,因此我们可以想办法通过尽量减少

    DOM操作来优化性能。

       首先,DOM操作为什么会影响性能。在浏览器中,DOM的实现和ECMAScript

    的实现是分离的。例如,在IE中,ECMAScript的实现在jscript.dll中,而DOM的

    实现在mshtml.dll中;在chrome中使用webkit的WebCore处理DOM和渲染,但

    ECMAScript是在V8引擎中实现的,其他浏览器的情况类似,所以通过Javascript

    调用dom接口,是相当于两个模块的交互。相比较在同一模块中的调用,这种跨模块的

    调用其性能损耗是很高的,但DOM操作对性能影响最大是因为它导致了浏览器的重绘

    和重排。

    浏览器渲染原理的简单说明

    从下载文档到渲染页面的过程中,浏览器会通过解析HTML文档来构建DOM树,解析

    CSS产生CSS规则树。javascript在代码解析的过程中,可能会修改生成的dom树

    和css规则树,之后根据dom树和css规则树构建渲染树,在这个过程中css会根据

    选择器匹配HTML元素。渲染树包括了每个元素的大小,边距等样式属性。渲染树

    中不包含隐藏元素及head元素等不可见元素。最后浏览器根据元素的坐标和大小

    来计算每个元素的位置,并绘制这些元素到页面上。重绘指的是元素的位置或尺寸

    发生了改变,浏览器会重新绘制页面上受影响的元素,重排的代价高于重绘。

    之下的DOM操作会导致重绘或重排:

      1.增加,删除和修改可见DOM元素

      2. 页面初始化的渲染

      3.移动dom元素

      4.修改css样式,改变dom元素的尺寸

      5.dom元素内容改变,使得尺寸被撑大

      6.浏览器窗口尺寸改变

      7.浏览器窗口滚动

    现代浏览器会针对重排或重绘做性能优化,例如,把DOM操作积累一批后统一

    做一次重排或重绘,但在有些情况下,浏览器会立即进行重排或重绘,比如请求如下的

    dom元素布局信息

    offsetTop/Left/Width/Height

    scrollTop/Left/Width/Height

    clientTop/Left/Width/Height

    getComputeStyle()或currentStyle

    因为这些值都是动态计算的,所以浏览器需尽快完成页面绘制,计算返回值,打乱了重绘或

    重排优化。

    可以遵循一些最佳实践来降低影响-->

    方法一:合并多此dom操作为单次dom操作

    通过class类名来元素的大量样式更改,代码维护性较好。

    通过innerHTML接口来修改DOM元素的内容时,以字符串方式拼接好代码后,一次性赋值给

    DOM元素的innerHTML接口。

    方法二: 把DOM元素离线或隐藏后修改

    把元素从页面流中脱离或隐藏,这样处理后,只会在DOM元素脱离或添加时,或者是隐藏或显示时才会造成页面的重绘会重排,对脱离了页面布局的DOM元素操作就不会导致页面的性能问题。

    这种方式适合需要大批量修改dom元素的情况。具体方式由三种:

    (1) 使用文档片段

    文档片段是一个轻量级的document对象,并不会和特定的页面关联,通过在文档片段上进行DOM操作,可以降低DOM操作对页面性能的影响,这种方式是创建一个文档片段,并在此片段上

    进行必要的DOM操作,操作完成后将它附加在页面中,对页面的影响只存在于最后把文档片段附加到页面的这一步操作上。

    var fragment=document.createDocumentFragment();

    //一些基于fragment的大量dom操作

    ...

    document.getElementById('myElement').appendChild(fragment);

    (2)隐藏元素

    通过隐藏元素,达到在页面上移除元素的效果,经过大量的DOM操作后恢复元素原来的display样式,只有隐藏和显示元素时会引起页面重绘或重排操作。

    var myElement=document.getElementById('myElement');
    myElement.style.display='none';

    //dom操作

    myElement.style.display='block';

    (3)克隆DOM元素到内存中

    把页面上的DOM元素克隆一份到内存中,然后在内存中操作克隆的元素,操作完成后使用此克隆元素替换页面中原来的DOM元素,只有替换元素时会影响性能,在内存中操作克隆元素不会引起页面上的性能损耗。

    var old=document.getElementById('myElement');

    var clone=old.cloneNode(true);

    //dom操作

    old.parentNode.replaceChild(clone,old);

    3.设置具有动画效果的DOM元素的position属性为fixed或absolute

    把页面中具有动画效果的元素设置为绝对定位,使得元素脱离页面布局流,从未避免了页面频繁的重排,只涉及动画元素自身的重排。这种做法可以提高动画效果的展示性能。(在动画开始时将其设置为绝对定位,等动画结束后恢复原始的定位设置)。

    4.谨慎获得dom元素的布局信息,变量本地化。

    把获取到的元素的布局信息值缓存在局部变量中。在有大量的DOM操作时,避免获取dom元素的布局信息,如果需要布局信息,最好在DOM操作之前就取好存放。

    5.使用事件托管方式绑定事件

    在DOM元素上绑定事件或影响页面的性能,一方面,绑定事件本身会占用处理时间,另一方面,浏览器保存事件绑定也会占用内存。使用事件托管方式,即利用事件冒泡机制,只在父元素上绑定事件处理,用于处理所有子元素的事件,在事件处理函数中根据传入的参数判断事件源元素,针对不同的元素做不同的处理。这种方式有很大的灵活性,可以方便的添加或删除子元素,不需要考虑因元素移除或添加需要修改事件绑定。

  • 相关阅读:
    [2010山东ACM省赛] Balloons(搜索)
    [2010山东ACM省赛] Greatest Number(数的组合+二分搜索)
    [ACM] hdu 1213 How Many Tables(并查集)
    C Shuffle Cards
    快速读入输出模板
    J Distance to Work
    E Sort String
    H Diff-prime Pairs
    A PACM Team
    区间 (interval)
  • 原文地址:https://www.cnblogs.com/jjworld/p/6491799.html
Copyright © 2020-2023  润新知