<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    emu in blogjava

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      171 隨筆 :: 103 文章 :: 1052 評論 :: 2 Trackbacks

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

    作者: KeeKim Heng, Google Web Developer

    在我們開發(fā)互聯(lián)網富應用(RIA)時,我們經常寫一些javascript腳本來修改或者增加頁面元素,這些工作最終是DOM——或者說文檔對象模型——來完成的,而我們的實現(xiàn)方式會影響到應用的響應速度。

    DOM操作會導致瀏覽器重解析(reflow),這是瀏覽器的一個決定頁面元素如何展現(xiàn)的計算過程。直接修改DOM,修改元素的CSS樣式,修改瀏覽器的窗口大小,都會觸發(fā)重解析。讀取元素的布局屬性比如offsetHeithe或者offsetWidth也會觸發(fā)重解析。重解析需要花費計算時間,因此重解析觸發(fā)的越少,應用就會越快。

    DOM操作通常要不就是修改已經存在的頁面上的元素,要不就是創(chuàng)建新的頁面元素。下面的4種優(yōu)化方案覆蓋了修改和創(chuàng)建DOM節(jié)點兩種方式,幫助你減少觸發(fā)瀏覽器重解析的次數。

    方案一:通過CSS類名切換來修改DOM 

    這個方案讓我們可以一次性修改一個元素和它的子元素的多個樣式屬性而只觸發(fā)一次重解析。

    需求:

    (emu注:原文作者寫到這里的時候腦子顯然短路了一下,把后面的Out-of-the-flow DOM Manipulation模式要解決的問題給擺到這里來了,不過從示范代碼中很容易明白作者真正想描述的問題,因此emu就不照翻原文了)

    我們現(xiàn)在需要寫一個函數來修改一個超鏈接的幾個樣式規(guī)則。要實現(xiàn)很簡單,把這幾個規(guī)則對應的屬性逐一改了就好了。但是帶來的問題是,每修改一個樣式屬性,都會導致一次頁面的重解析。

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

     

    解決方案

    要解決這個問題,我們可以先創(chuàng)建一個樣式名,并且把要修改的樣式規(guī)則都放到這個類名上,然后我們給超鏈接添加上這個新類名,就可以實現(xiàn)添加幾個樣式規(guī)則而只觸發(fā)一次重解析了。這個模式還有個好處是也實現(xiàn)了表現(xiàn)和邏輯相分離。


     

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

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

    方案二:在非渲染區(qū)修改DOM

    (emu注:作者在這里再次腦子短路,把DocumentFragment DOM Generation模式的介紹提前到這里來了,emu只好再次發(fā)揮一下)
    上一個方案解決的是修改一個超鏈接的問題,當一次需要對很多個超鏈接進行相同修改的時候,這個方案就可以大顯身手了。

    需求

    需求是這樣的,我們要寫一個函數來修改一個指定元素的子元素中所有的超鏈接的樣式名(className)屬性。要實現(xiàn)很簡單,我們可以通過遍歷每個超鏈接并且修改它們的樣式名來完成任務。但是帶來的問題就是,每修改一個超鏈接都會導致一次重解析。

    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節(jié)點,還返回了一個把元素插回到原來的位置的函數。

    /**
     * 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);
        }
      };
    }

    有了上面這個函數,現(xiàn)在我們就可以在一個不需要解析渲染的元素上面修改那些超鏈接了。這樣只在移除和插入元素的時候各觸發(fā)一次重解析。
    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元素生成

    這個方案讓我們創(chuàng)建一個元素的過程只觸發(fā)一次重解析。在創(chuàng)建完元素以后,先進行所有需要的修改,最后才把它插入到DOM里面去就可以了

    需求

    需求是這樣的,實現(xiàn)一個函數,往一個指定的父元素上插入一個超鏈接元素。這個函數要同時可以設置這個超鏈接的顯示文字和樣式類。我們可以這樣做:創(chuàng)建元素,插入到DOM里面,然后設置相應的屬性。這就要觸發(fā)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);
    }

    不過,要是我們想要插入很多個超鏈接到一個元素里面的話,那么這個做法還是有問題:每插入一個超鏈接還是要觸發(fā)一次重解析。下一個方案可以解決這個問題。

    方案四:通過文檔片段對象(DocumentFragment)創(chuàng)建一組元素

    這個方案允許我們創(chuàng)建并插入很多個元素而只觸發(fā)一次重解析。要實現(xiàn)這點需要用到所謂的文檔片段對象(DocumentFragment)。我們先在DOM之外創(chuàng)建一個文檔片段對象(這樣它也就不需要解析和渲染),然后我們在文檔片段對象中創(chuàng)建很多個元素,最后我們把這個文檔片段對象中所有的元素一次性放到DOM里面去,只觸發(fā)一次重解析。

    需求


    我們要寫一個函數,往一個指定的元素上面增加10個超鏈接。如果我們簡單的直接插入10個超鏈接到元素上面,就會觸發(fā)10次重解析。

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

    解決方案

    要解決這個問題,我們要先創(chuàng)建一個文檔片段對象,然后把每個新創(chuàng)建的超鏈接都插入到它里面去。當我們把文檔片段對象用appendChild命令插入到指定的節(jié)點時,這個文檔片段對象的所有子節(jié)點就一起被插入到指定的元素里面,而且只需要觸發(fā)一次重解析。

    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);
    }


    注意:如無特別聲明,本文中引用的所有程序均不是Google開發(fā),也與Google沒有其他什么關系。這些程序引發(fā)的責任均由其開發(fā)者或者所有者自己承擔,與google無關。
    posted on 2010-03-01 17:20 emu 閱讀(4115) 評論(4)  編輯  收藏 所屬分類: web優(yōu)化

    評論

    # re: [翻譯]加速Javascript:DOM操作優(yōu)化 2010-03-02 08:45 Allen.M
    怎么沒翻譯完?后面的沒了?  回復  更多評論
      

    # re: [翻譯]加速Javascript:DOM操作優(yōu)化 2010-03-02 09:29 emu
    @Allen.M
    抱歉,昨天可能誤操作了,已經補齊。  回復  更多評論
      

    # re: [翻譯]加速Javascript:DOM操作優(yōu)化 2010-03-16 09:43 殘冰
    不錯,謝謝,繼續(xù)努力  回復  更多評論
      

    # re: [翻譯]加速Javascript:DOM操作優(yōu)化 2011-05-07 15:45 gujian
    這個地方寫的也不錯可以參考:
    http://www.01yun.com/jssx  回復  更多評論
      

    主站蜘蛛池模板: 热久久这里是精品6免费观看| 国产成人精品久久亚洲高清不卡| 黄网站色成年片大免费高清| 最近2019中文字幕mv免费看| 亚洲一区二区久久| 免费看成人AA片无码视频羞羞网| 亚洲自偷精品视频自拍| 最好看的中文字幕2019免费| 亚洲视频小说图片| 一个人免费观看视频www| 色偷偷女男人的天堂亚洲网| 成人a视频片在线观看免费| 亚洲国产精品成人午夜在线观看 | 久久精品国产亚洲精品| 亚洲高清免费视频| 国产精一品亚洲二区在线播放| 女同免费毛片在线播放| 亚洲AV无码精品色午夜果冻不卡| 无码av免费网站| 亚洲综合校园春色| 国产免费小视频在线观看| jizz免费观看视频| 亚洲AV本道一区二区三区四区 | 成人毛片手机版免费看| 国产亚洲男人的天堂在线观看| 亚洲七久久之综合七久久| 成人免费无遮挡无码黄漫视频| 日韩成人精品日本亚洲| 久久久久久亚洲精品不卡| 免费人成视频在线观看网站| 久久乐国产精品亚洲综合| 免费一级毛片无毒不卡| 国产亚洲sss在线播放| 免费国产成人高清视频网站| 最近的2019免费中文字幕| 久久精品国产亚洲AV蜜臀色欲 | 中文字幕在线免费| 国产精品久久久久久亚洲小说 | 亚洲成AV人片在线观看| 香蕉免费在线视频| 亚洲国产电影在线观看|