zoukankan      html  css  js  c++  java
  • 前端页面卡顿-代码优化

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

  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/jjworld/p/6491799.html
Copyright © 2011-2022 走看看