`
fuhao200866
  • 浏览: 78480 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

减少浏览器重解析 JavaScript DOM操作优化方案

阅读更多

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

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

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

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

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

需求

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

  1. function selectAnchor(element) {  
  2.   element.style.fontWeight = 'bold';  
  3.   element.style.textDecoration = 'none';  
  4.   element.style.color = '#000';  

解决方案

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

  1. .selectedAnchor {  
  2.   font-weight: bold;  
  3.   text-decoration: none;  
  4.   color: #000;  
  5. }  
  6. function selectAnchor(element) {  
  7.   element.className = 'selectedAnchor';  

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

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

需求

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

  1. function updateAllAnchors(element, anchorClass) {  
  2.   var anchors = element.getElementsByTagName('a');  
  3.   for (var i = 0length = anchors.length; i < length; i ++) {  
  4.      anchors.className = anchorClass;  
  5.   }  

解决方案

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

  1. /**  
  2. * Remove an element and provide a function that inserts it into its original position  
  3. * @param element {Element} The element to be temporarily removed  
  4. * @return {Function} A function that inserts the element into its original position  
  5. **/  
  6.  
  7. function removeToInsertLater(element) {  
  8.   var parentNode = element.parentNode;  
  9.   var nextSibling = element.nextSibling;  
  10.   parentNode.removeChild(element);  
  11.   return function() {  
  12.     if (nextSibling) {  
  13.        parentNode.insertBefore(element, nextSibling);  
  14.     } else {  
  15.    parentNode.appendChild(element);  
  16.     }  
  17.   };  

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

  1. function updateAllAnchors(element, anchorClass) {  
  2.   var insertFunction = removeToInsertLater(element);  
  3.   var anchors = element.getElementsByTagName('a');  
  4.   for (var i = 0length = anchors.length; i < length; i ++) {  
  5.      anchors.className = anchorClass;  
  6.   }  
  7.     insertFunction();  

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

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

需求

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

  1. function addAnchor(parentElement, anchorText, anchorClass) {  
  2.   var element = document.createElement('a');  
  3.   parentElement.appendChild(element);  
  4.   element.innerHTML = anchorText;  
  5.   element.className = anchorClass;  

解决方案

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

  1. var element = document.createElement('a');  
  2. element.innerHTML = anchorText;  
  3. element.className = anchorClass;  
  4. parentElement.appendChild(element);  

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

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

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

需求

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

  1. function addAnchors(element) {  
  2. var anchor;  
  3. for (var i = 0; i < 10; i ++) {  
  4.     anchor = document.createElement('a');  
  5.     anchor.innerHTML = 'test';  
  6.     element.appendChild(anchor);  
  7.     }  

解决方案

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

  1. function addAnchors(element) {  
  2.   var anchor, fragment = document.createDocumentFragment();  
  3.   for (var i = 0; i < 10; i ++) {  
  4.     anchor = document.createElement('a');  
  5.     anchor.innerHTML = 'test';  
  6.     fragment.appendChild(anchor);  
  7.   }  
  8.   element.appendChild(fragment);  
分享到:
评论

相关推荐

    嵌入式浏览器中JavaSCript和DOM的支持.pdf

    - **性能优化**:减少解析和执行JavaScript及DOM操作的时间,可能需要使用如即时编译(JIT)等技术。 - **资源占用**:尽量减小代码体积和运行时的资源消耗,如使用紧凑的数据结构和算法。 - **功耗控制**:在不影响...

    javascript DOM 操作.doc

    javascript DOM 操作 javascript DOM 操作是指在客户端使用javascript语言来操作文档对象模型...javascript DOM 操作可以在客户端动态地更改网页的内容和结构,但是在不同的浏览器中需要使用不同的方法和属性来实现。

    c#操作浏览器dom对象

    综上所述,学习C#操作浏览器DOM对象涉及多个层次的知识,从理解DOM的概念到熟悉使用自动化工具和库,以及如何与JavaScript和网页交互。实践中,开发者需要具备一定的HTML和CSS理解能力,以及对异步编程和错误处理的...

    记录我的旅程之JavaScript Dom系列里面的所有例题

    总的来说,这个“记录我的旅程之JavaScript DOM系列”涵盖了DOM操作的各个方面,包括元素的查找、创建、修改、删除、事件处理、动画和性能优化。通过实践这些例题,你将能更熟练地驾驭JavaScript与DOM的交互,提升...

    dom解析器 动态修改当前页面

    在实际应用中,DOM解析器不仅限于IE,现代浏览器如Chrome、Firefox等都提供了强大的DOM操作工具,如Chrome的开发者工具和Firefox的Web Console。这些工具同样可以用来查看和修改DOM,且兼容性更佳,功能更全面。 总...

    JavaScript+DOM编程艺术(PDF格式原版+源代码)

    DOM是HTML和XML文档的标准表示方式,它是浏览器用来解析和操作网页内容的对象模型。JavaScript通过DOM API可以访问和修改网页的任何元素,实现动态更新、事件处理等功能。DOM编程艺术这部分内容将详细介绍如何使用...

    JavaScript-DOM.rar_javascript

    DOM是独立于语言的标准,但JavaScript是最常用来操作DOM的语言,因此JavaScript DOM在前端开发中扮演着核心角色。 一、JavaScript DOM的本质 DOM本质是一个树形结构,它将网页内容视为节点层次,其中每个元素、属性...

    浏览器渲染过程及优化策略

    浏览器渲染优化策略包括减少 repaint 和 reflow、合理使用缓存、使用 CSS 动画、避免过多的 DOM 操作、使用 lazy loading 等。这些策略可以减少浏览器的渲染时间,提高浏览器的性能和用户体验。 在浏览器渲染过程中...

    JavaScript DOM高级程序设计

    9. **DOM性能优化**:频繁操作DOM会导致页面重绘和回流,影响性能。通过创建文档碎片(`document.createDocumentFragment()`)、批量操作和缓存引用等方法可以优化DOM操作。 10. **jQuery和其他库**:虽然本资源...

    JavaScript DOM 编程艺术1

    - 性能优化:减少DOM操作次数,合并和合理放置脚本,压缩代码以提升加载速度。 7. 动态创建标记: - 使用传统方法如document.write和innerHTML属性动态生成或修改HTML内容。 - DOM方法如createElement、...

    JavaScript dom编程艺术:个人笔记.pdf

    2. DOM结构解析:DOM(Document Object Model,文档对象模型)是JavaScript操作HTML文档的接口。了解DOM的树状结构,能够熟练地访问和修改DOM节点,包括创建、插入、删除和替换节点等。 3. 事件处理:事件处理是...

    谷歌获取网页dom的插件

    JavaScript在现代网页中的作用巨大,许多动态内容是通过JS生成的,因此,能够解析和操作DOM对于抓取这些动态数据至关重要。 在爬取过程中,插件通常扮演着辅助角色,它提供了一种便捷的方式来查看和操作DOM结构。...

    javascript DOM 高级程序设计源码(1)

    在性能优化方面,我们应该避免频繁的DOM操作,因为这会导致浏览器重绘和回流,影响用户体验。可以使用`innerHTML`一次性设置或获取大量内容,或者使用`textContent`代替,避免解析HTML。另外,利用`...

    JavaScript DOM编程艺术 源代码

    9. **DOM操作最佳实践**:性能优化是任何Web开发中的重要环节,避免频繁操作DOM、使用事件委托、缓存引用等都是提高性能的有效手段。 10. **ES6及后续版本的新特性**:随着JavaScript的发展,许多新特性如箭头函数...

    Javascript DOM编程艺术及源代码

    9. **性能优化**:频繁的DOM操作可能导致性能下降,因此应尽量减少DOM操作次数,使用DocumentFragment批量操作,或者利用事件委托等技巧提高效率。 10. **框架和库的支持**:现代前端框架如React、Vue、Angular等,...

    常用的DOM优化.pdf

    ### 常用的DOM优化 #### DOM与前端性能优化 随着互联网技术的发展及用户体验的不断提升,前端性能优化成为开发者必须关注的重点之一。DOM(Document Object Model)作为HTML和XML文档的标准对象模型,在前端开发中...

    javascript 操作xml_dom对象整理集合

    综上所述,JavaScript操作XML DOM对象涉及到了从解析XML到动态操作文档的各个层面,同时结合JavaScript技巧,可以实现高效、灵活的Web应用开发。通过不断学习和实践,开发者能更好地驾驭这个强大的工具集。

Global site tag (gtag.js) - Google Analytics