原文:《Speeding up JavaScript: Working with the DOM》

作者: KeeKim Heng, Google Web Developer

在我们开发互联网富应用(RIA)时,我们经常写一些javascript脚本来修改或者增加页面元素,这些工作最终是DOM——或者说文档对象模 型——来完成的,而我们的实现方式会影响到应用的响应速度。

DOM操作会导致浏览器重解析(reflow),这是浏览器的一个决定页面元素如何展现的计算过程。直接修改DOM,修改元素的CSS样式,修改浏 览器的窗口大小,都会触发重解析。读取元素的布局属性比如offsetHeithe或者offsetWidth也会触发重解析。重解析需要花费计算时间, 因此重解析触发的越少,应用就会越快。

DOM操作通常要不就是修改已经存在的页面上的元素,要不就是创建新的页面元素。下面的4种优化方案覆盖了修改和创建DOM节点两种方式,帮助你减 少触发浏览器重解析的次数。

方案一:通过CSS类名切换来修改DOM

这个方案让我们可以一次性修改一个元素和它的子元素的多个样式属性而只触发一次重解析。

需求:

我们现在需要写一个函数来修改一个超链接的几个样式规则。要实现很简单,把这几个规则对应的属性逐一改了就好了。但是带来的问题是,每修改一个样式 属性,都会导致一次页面的重解析。

function selectAnchor(element) {
  element.style.fontWeight = 'bold';
  element.style.textDecoration = 'none';
  element.style.color = '#000';
}

解决方案

要解决这个问题,我们可以先创建一个样式名,并且把要修改的样式规则都放到这个类名上,然后我们给超链接添加上这个新类名,就可以实现添加几个样式 规则而只触发一次重解析了。这个模式还有个好处是也实现了表现和逻辑相分离。

.selectedAnchor {
  font-weight: bold;
  text-decoration: none;
  color: #000;
}

function selectAnchor(element) {
  element.className = 'selectedAnchor';
}

方案二:在非渲染区修改DOM

上一个方案解决的是修改一个超链接的问题,当一次需要对很多个超链接进行相同修改的时候,这个方案就可以大显身手了。

需求

需求是这样的,我们要写一个函数来修改一个指定元素的子元素中所有的超链接的样式名(className)属性。要实现很简单,我们可以通过遍历每 个超链接并且修改它们的样式名来完成任务。但是带来的问题就是,每修改一个超链接都会导致一次重解析。

function updateAllAnchors(element, anchorClass) {
  var anchors = element.getElementsByTagName('a');
  for (var i = 0, length = anchors.length; i < length; i ++) {
    anchors[i].className = anchorClass;
  }
}

解决方案

要解决这个问题,我们可以把被修改的指定元素从DOM里面移除,再修改所有的超链接,然后在把这个元素插入回到它原来的位置上。为了完成这个复杂的 操作,我们可以先写一个可重用的函数,它不但移除了这个DOM节点,还返回了一个把元素插回到原来的位置的函数。

/**
 * Remove an element and provide a function that inserts it into its original position
 * @param element {Element} The element to be temporarily removed
 * @return {Function} A function that inserts the element into its original position
 **/
function removeToInsertLater(element) {
  var parentNode = element.parentNode;
  var nextSibling = element.nextSibling;
  parentNode.removeChild(element);
  return function() {
    if (nextSibling) {
      parentNode.insertBefore(element, nextSibling);
    } else {
      parentNode.appendChild(element);
    }
  };
}

有了上面这个函数,现在我们就可以在一个不需要解析渲染的元素上面修改那些超链接了。这样只在移除和插入元素的时候各触发一次重解析。

function updateAllAnchors(element, anchorClass) {
  var insertFunction = removeToInsertLater(element);
  var anchors = element.getElementsByTagName('a');
  for (var i = 0, length = anchors.length; i < length; i ++) {
    anchors[i].className = anchorClass;
  }
  insertFunction();
}

方案三:一次性的DOM元素生成

这个方案让我们创建一个元素的过程只触发一次重解析。在创建完元素以后,先进行所有需要的修改,最后才把它插入到DOM里面去就可以了

需求

需求是这样的,实现一个函数,往一个指定的父元素上插入一个超链接元素。这个函数要同时可以设置这个超链接的显示文字和样式类。我们可以这样做:创 建元素,插入到DOM里面,然后设置相应的属性。这就要触发3次重解析。

function addAnchor(parentElement, anchorText, anchorClass) {
  var element = document.createElement('a');
  parentElement.appendChild(element);
  element.innerHTML = anchorText;
  element.className = anchorClass;
}

解决方案

很简单,我们只要把插入元素这个操作放到最后做,就可以只进行一次重解析了。

function addAnchor(parentElement, anchorText, anchorClass) {
  var element = document.createElement('a');
  element.innerHTML = anchorText;
  element.className = anchorClass;
  parentElement.appendChild(element);
}

不过,要是我们想要插入很多个超链接到一个元素里面的话,那么这个做法还是有问题:每插入一个超链接还是要触发一次重解析。下一个方案可以解决这个 问题。

方案四:通过文档片段对象(DocumentFragment)创建一组元素

这个方案允许我们创建并插入很多个元素而只触发一次重解析。要实现这点需要用到所谓的文档片段对象(DocumentFragment)。我们先在 DOM之外创建一个文档片段对象(这样它也就不需要解析和渲染),然后我们在文档片段对象中创建很多个元素,最后我们把这个文档片段对象中所有的元素一次 性放到DOM里面去,只触发一次重解析。

需求

我们要写一个函数,往一个指定的元素上面增加10个超链接。如果我们简单的直接插入10个超链接到元素上面,就会触发10次重解析。

function addAnchors(element) {
  var anchor;
  for (var i = 0; i < 10; i ++) {
    anchor = document.createElement('a');
    anchor.innerHTML = 'test';
    element.appendChild(anchor);
  }
}

解决方案

要解决这个问题,我们要先创建一个文档片段对象,然后把每个新创建的超链接都插入到它里面去。当我们把文档片段对象用appendChild命令插 入到指定的节点时,这个文档片段对象的所有子节点就一起被插入到指定的元素里面,而且只需要触发一次重解析。

function addAnchors(element) {
  var anchor, fragment = document.createDocumentFragment();
  for (var i = 0; i < 10; i ++) {
    anchor = document.createElement('a');
    anchor.innerHTML = 'test';
    fragment.appendChild(anchor);
  }
  element.appendChild(fragment);
}

转载于:https://www.cnblogs.com/MaxIE/archive/2010/03/11/1683501.html

加速Javascript:DOM操作优化相关推荐

  1. 视频教程-Javascript DOM操作-JavaScript

    Javascript DOM操作 江湖花名King... 何山 ¥39.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 APP订阅课程,领取优惠,最少立减5元 ↓↓↓ ...

  2. javascript DOM 操作

    在javascript中,经常会需要操作DOM操作,在此记录一下学习到DOM操作的知识. 一.JavaScript DOM 操作 1.1.DOM概念 DOM :Document Object Mode ...

  3. JavaScript DOM操作Select下拉框

    DOM操作Select下拉框: 获取select选中的option值,修改选中的选项,添加选项option. <body> <script type="text/javas ...

  4. JavaScript DOM操作为什么会影响性能

    DOM操作影响性能的原因主要有以下两点: 在浏览器中,DOM的实现和ECMAScript的实现是分离的.比如在Chrome中使用WebKit中的WebCore处理DOM和渲染,但ECMAScript是 ...

  5. java svg 读取dom结构_SVG基础以及使用Javascript DOM操作SVG

    SVG 不依赖分辨率 支持事件处理器 最适合带有大型渲染区域的应用程序(比如谷歌地图) 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快) 不适合游戏应用 Canvas 依赖分辨率 不支持事 ...

  6. JavaScript DOM操作表格及样式

    一 操作表格 <table>标签是HTML中结构最为复杂的一个,我们可以通过DOM来创建生成它,或者HTMLDOM来操作它; 1 2 3 4 5 6 7 8 9 10 11 12 13 1 ...

  7. 常见的原生javascript DOM操作

    1.创建元素 创建元素:document.createElement() 使用document.createElement()可以创建新元素.这个方法只接受一个参数,即要创建元素的标签名.这个标签名在 ...

  8. JavaScript DOM操作,就是这么简单!

    DOM,即文档对象模型(Document Object Model),是通过JavaScript来对HTML文档进行管理和操作的一类 对象模型,通过DOM可以操作HTML的元素和元素的属性,包括对元素 ...

  9. 【收藏】JavaScript DOM操作简易速查手册

    附Java/C/C++/机器学习/算法与数据结构/前端/安卓/Python/程序员必读书籍书单大全: 书单导航页(点击右侧 极客侠栈 即可打开个人博客):极客侠栈 ①[Java]学习之路吐血整理技术书 ...

最新文章

  1. 利用正则表达式去除所有html标签,只保留文字
  2. U启动安装原版Win7系统教程
  3. POSIX 信号量和互斥锁
  4. python开发效率怎样提高_python 提高开发效率的5个小技巧
  5. Seven Kinds of Testers - 七种类型的测试
  6. pg数据库多表查询(inner)和级联查询
  7. ANT安装(亲测可用)
  8. java的链表(LinkedList类)
  9. 计算机多媒体英语,基于计算机多媒体的英语个性化教学
  10. html+盒子+边距,盒子模型、边框、边距
  11. 为河南小伙恩辉舍己救人点赞<原创>
  12. Java狐仙ol,狐仙八大职业介绍 简要分为四类
  13. 访问学者在美国访学衣食住行的小妙招
  14. Matlab中将多维数组转换为一维数组
  15. com.yjh.entity.Student Not Found TableInfoCache.
  16. 嘿!大三了怎么找到对象?膜拜!
  17. MAC查看库信息/rpath(类似ldd)otool
  18. 极域电子教室远程操作命令运行应用程序
  19. 企业数据中心如何挑选机柜
  20. 9月25日,AWSUnitimes免费请您吃晚餐啦!

热门文章

  1. Atlas, AJAX
  2. 让Qt应用程序跑在Android上
  3. Linux运维架构师、SRE技术图谱
  4. python 修改字符串 循环_python – 模式匹配并用if else循环替换字符串
  5. python语言特点依赖平台吗_python语言的特点
  6. c# spire.xls 设置文字为微软雅黑_Excel工作薄常规样式设置,WorkBook.Styles
  7. P1115 最大子段和
  8. 1768: 回文平方数(进制转换)
  9. 云原生乘风者联合征文活动——说出你和「阿里云云原生」的故事
  10. 云原生数据库 2.0:一站式全链路数据管理与服务