2010-01-28 173 views
0

我需要讓這個jquery運行得更快,我沒有創建所有這些函數,但需要他們的方法來做頁面內容的實時轉換。請幫我重構這個jQuery代碼

所以,我將不勝感激任何建議,以改善性能,下面的代碼重構。


/* function 1 read json into array */ 
/* function 2 loop through array */ 
/* function 3 replace text nodes based on data from looped array */ 

var en_lang = new Array(); 
var fr_lang = new Array(); 
var frca_lang = new Array(); 
var my_data = null; 
var en_count = 1; 
var fr_count = 1; 
var frca_count = 1; 

if(typeof(language) != "undefined"){ 
    var language = 'frca'; 
} 

function replaceText(oldText, newText, node){ 
    node = node || document.body; // base node 

    var childs = node.childNodes, i = 0; 

    while(node = childs[i]){ 
    if (node.nodeType == 3){ // text node found, do the replacement 
     if (node.textContent) { 
     node.textContent = node.textContent.replace(oldText, newText); 
     } else { // support to IE 
     node.nodeValue = node.nodeValue.replace(oldText, newText); 
     } 
    } else { // not a text mode, look forward 
     replaceText(oldText, newText, node); 
    } 
    i++; 
    } 
} 
function parsejSON(my_data) { 
    /* THIS PART GRABS DATA FROM TOP OF JSON FILE */ 

    /* grab recordcount */ 
    var recordcount = my_data.recordcount; 
    /* grab columnlist */ 
    var columnlist = my_data.columnlist; 
    /* grab json data */ 
    var json_data = my_data.data; 

    /* PUTS JSON DATA INTO ARRAYS */ 
    for(var x = 0; x < recordcount; x++) { 
     var lng = json_data.lng[x]; 
     var phrase = json_data.phrase[x]; 

     if (lng == 'french') { 

      fr_lang[fr_count] = phrase; 
      fr_count = fr_count + 1; 
     } 
     if (lng == 'french canadian') { 

      frca_lang[frca_count] = phrase; 
      frca_count = frca_count + 1; 
     } 
     if (lng == 'english') { 

      en_lang[en_count] = phrase; 
      en_count = en_count + 1; 
     } 
    } 

    /* use a replacetext function above to replace all text */ 

    for(var x = 0; x < en_lang.length; x++) { 
     var from = en_lang[x]; 
     if (language == 'fr') { 
     var to = fr_lang[x]; 
     } 
     if (language == 'frca') { 
     var to = frca_lang[x]; 
     } 
     replaceText(from, to); 
    } 



} 

不好意思,不太清楚如何讓代碼發佈,格式正確,隨意編輯我在那種情況下後..

謝謝。

+0

我在這裏沒有看到任何jQuery。你的意思是JavaScript嗎? – artlung 2010-01-28 17:57:12

+0

我相信,我修剪了jquery。對不起,如果不清楚,並感謝您爲我編輯它。 – crosenblum 2010-01-28 18:03:03

回答

2

通過檢查你的代碼,我可以告訴你,你的大部分開銷創建在replaceText函數中。對於每個文本項目,您的代碼一次又一次遍歷整個DOM結構。代碼不是一次完成,而是通過文件en_lang.length多次。節點操作要比JavaScript代碼慢得多,所以如果你的en_lang數組中有很多項目,並且文檔結構很複雜,那麼渲染時間會急劇增加。通過在一個循環中替換所有文本項目將節省大量時間。

二。我可以看到,在執行分配操作的每個節點上。 node.textContent = node.textContent.replace(oldText, newText); 如果您的節點不包含任何匹配信息,則此操作過量。通過僅在需要的地方進行DOM分配,您可以爲自己節省另一個渲染時間。

三。遞歸。真正有趣的話題。可以使用,不能使用。你更喜歡什麼。但有時遞歸可能是代碼中的瓶頸。在這種情況下,replaceText是一個recusrive操作,這會導致不需要的內存消息和CPU時間。您可以通過使用getElementsByTagName函數詢問它來一步獲取所有節點。

第四個:「if」在第一個for循環的「parseJson」裏面的操作。我不知道爲什麼,但是你不使用if-else語句,但是很簡單。這意味着即使已經找到正確的語句,運行時也應該通過所有的「if」語句。在這種情況下,爲了提高JavaScript效率,最好使用「switch」語句而不是「if」或「if-else」。速度更快。

五。現在讓我們看看第二個「for」循環。你不應該在那裏使用任何開關或聲明。該部分中的「if」陳述完全矯枉過正。在for循環之前,您知道「language」變量的值,因此您可以在for循環之前緩存「to」數組並使用已經緩存的數組。六:另一個小小的改進,而不是使用frca_count = frca_count + 1;而不是使用frca_count = frca_count + 1。你可以使用增量運算符:frca_count ++。它也將加速代碼。

七。在你的第二個for:語句中,你在條件部分使用了en_lang.length,如果你看一下前面的for循環,你可以看到它有一個包含相同值的變量:「en_count」,用它代替en_lang。長度加快循環本身。

結合這一切,我想出了這樣的事情。

function parsejSON(my_data) { 
/* THIS PART GRABS DATA FROM TOP OF JSON FILE */ 

/* grab recordcount */ 
var recordcount = my_data.recordcount; 
/* grab columnlist */ 
var columnlist = my_data.columnlist; 
/* grab json data */ 
var json_data = my_data.data; 

/* PUTS JSON DATA INTO ARRAYS */ 
for(var x = 0; x < recordcount; x++) { 
    var lng = json_data.lng[x]; 
    var phrase = json_data.phrase[x]; 

// (conclusion # 4) 
    switch(lng){ 
    case 'french': 
    // (conclusion # 6) 
    fr_lang[fr_count++] = phrase; 
    break; 
    case 'french canadian': 
    frca_lang[frca_count++] = phrase; 
    break; 
    case 'english': 
    en_lang[en_count++] = phrase; 
    break; 
    } 
} 

/* use a replacetext function above to replace all text */ 
// (conclusion # 5) 
var toCache = (language == 'fr') ? fr_lang 
: (language == 'frca' ? frca_lang : null); 


// (conclusion # x) 
var content = function(node, txt){ 
    if(txt){ 
    if(node.textContent){ 
    node.textContent = txt; 
    }else if(node.nodeValue){ 
    node.nodeValue = txt; 
    } 
    }else{ 
    return node.textContent ? node.textContent : node.nodeValue; 
    } 
}; 

// recursive tree walker 
(function(parent){ 
    var childs = parent.childNodes; 
    if(childs && childs.length){ 
     for(var i=0,node;node = childs[i];i++){ 
      if(node.nodeType == 3){ // text node found, do the replacement 
       var value = content(node); 
       // (conclusion # 7) 
       for(var x = 0; x < en_count; x++) { 
        var from = en_lang[x]; 
        var to = toCache[x]; 
        // (conclusion # 2) 
        if(value.match(from)){ 
         content(node, value.replace(from,to)); 
        } 
       } 
      }else{ 
       arguments.callee(node); 
      } 
     } 
    } 
})(document.body); 

}

所有應該做的伎倆,我希望。祝你好運

EDITED:因爲getElementsByTagName(「*」)不會返回#text節點,所以我更改了使用遞歸樹walker的解決方案。

+0

我得到一個錯誤的孩子沒有定義,爲while while循環下結論#1 – crosenblum 2010-02-01 19:59:24

+0

我修復了錯誤,沒有更多的錯誤,但它什麼都沒做。 – crosenblum 2010-02-01 20:10:06

+0

我改變了我的答案,完全忘了getElementsByTagName不返回文本節點。現在就試試。 – nemisj 2010-02-01 21:43:45

0

你可以試試firebug中的console.time。這會告訴您在進行更改時您節省了多少時間。它也將幫助你找出哪些功能需要最長的執行(這樣你就可以解決先優化它們。)

How to measure time taken by a function to execute

0

我建議將每個本地化參數放入span標籤中,然後您可以更輕鬆地選擇和更新您的參數。擁有.localize類名,具有.l-PARMNAME類名的allong將具有相當嚴格的可選性。

例如:<span class="localize l-PARMNAME">English Value</span>

然後你可以有你的數據...

jsonData: { //note: this can come back from your ajax call 
    language:'fr', 
    parms: { 
    "PARMNAME": "parm value", 
    "OTHERPARM": "other value", 
    ... 
    } 
} 


$.each(jsonData.parms, function(key, value){ 
    ($('span.localize.l-'+key).text(value); 
}); 

上面的代碼應該運行快一點(使用jQuery)在最近的瀏覽器,有一個更好的選擇是模型。它幾乎可以在任何瀏覽器中運行。如果性能仍然是一個問題,可以通過$(「span.localize」)。each()進行循環,並檢查相應的子標籤。否則,你可以簡單地對你的英文版本進行循環,但我會建議對每個可複製節點使用span標籤。即使只是「span.localize」選擇器會給你一個較小的節點,你可以比較.text()的值,並匹配/替換整個字符串...在文本節點內的字符串上使用.replace是公平的很重要,因爲你必須得到文本的值,匹配字符串(基於正則表達式),然後將新值輸入到文本節點。能夠有一個狹窄的標籤選擇器,從那裏能夠專門針對你想要的節點將在新的瀏覽器中改進dom搜索。

+0

不可能,使用此版本的代碼。我們只需修改100個頁面即可進行服務器端文件更改。這就是爲什麼我們必須依賴現有的代碼,但進行客戶端更改。 – crosenblum 2010-02-08 17:51:55