2012-02-13 17 views
0

Javascript(Mootools)を使用して、HTMLテンプレートの要素を使用して大きなページを動的に作成し、同じテンプレートを何度もコピーしてページに挿入します。各テンプレート内では、一意のIDを作成するために置換する必要がある文字列キーワードを使用します。しかし、特にIEでこれらの置換えをすべて実行するには、数秒かかるという点で重大なパフォーマンス上の問題があります。コードは次のようになります。JavascriptのHTMLブロック内の文字列を効率的に置き換える

var fieldTemplate = $$('.fieldTemplate')[0]; 
var fieldTr = fieldTemplate.clone(true, true); 
fieldTr.removeClass('fieldTemplate'); 
replaceIdsHelper(fieldTr, ':FIELD_NODE_ID:', fieldNodeId); 
parentTable.grab(fieldTr); 

replaceIdsHelper()は、IE9のプロファイラによる問題の方法です。これらのアプローチの両方が、この方法は、(約200 ...)呼び出される回数を与えられた非常に遅いです、しかし

// Retrieve the entire HTML body of the element, replace the string and set the HTML back. 
var html = rootElem.get('html').replace(new RegExp(replaceStr, 'g'), id); 
rootElem.set('html', html); 

// Load the child elements and replace just their IDs selectively 
rootElem.getElements('*').each(function(elem) { 
    var elemId = elem.get('id'); 
    if (elemId != null) elemId = elemId.replace(replaceStr, id); 
    elem.set('id', elemId) 
}); 

:私はこの方法の2つの実装を試みました。他のすべては正常に動作しますが、これは重要なパフォーマンスのボトルネックと思われるこれらのIDを置き換えるだけです。これを効率的にやり遂げる方法があるのか​​、そんなに遅く動いているのか誰にも分かりますか?要素は非表示になり、DOMが作成されてから再描画が行われるまでDOMによって取得されません。

ところで、このようにページを構築しているのは、ロード後も新しい要素を動的に作成できるようにする必要があるためです。これをサーバー側から行うと、はるかに複雑になります。

答えて

1

あなたがそれを最適化するためにできることがいくつかあります。@ nizan tomerは非常に良いと言いますが、疑似テンプレートは良いパターンです。

まず、

としてあなたがこれを行う必要があります
var fieldTemplate = $$('.fieldTemplate')[0]; 
var fieldTr = fieldTemplate.clone(true, true); 

:テンプレート自体は/のように例えば、提案することができなければならない

var templateHTML = somenode.getElement(".fieldTemplate").get("html"); // no need to clone it. 

<td id="{id}">{something}</td> 

だけ、一回のためにそれをクローンする必要がそれを読んでいません代わりに、新しいElementコンストラクタを使用してinnerHTMLを設定します - <tr> </tr>がないことに注意してください。

あなたはデータを持つオブジェクト、例えばを持っている場合:

var rows = [{ 
    id: "row1", 
    something: "hello" 
}, { 
    id: "row2", 
    something: "there" 
}]; 

Array.each(function(obj, index) { 
    var newel = new Element("tr", { 
     html: templateHTML.substitute(obj) 
    }); 
    // defer the inject so it's non-blocking of the UI thread: 
    newel.inject.delay(10, newel, parentTable); 
    // if you need to know when done, use a counter + index 
    // in a function and fire a ready. 
}); 

代わりに、使用した文書の断片: http://jsperf.com/inject-vs-fragment-in-mootools

:私はこれらのメソッドの両方にjsperfテストを行った

Element.implement({ 
    docFragment: function(){ 
     return document.createDocumentFragment(); 
    } 
}); 

(function() { 
    var fragment = Element.docFragment(); 

    Array.each(function(obj) { 
     fragment.appendChild(new Element("tr", { 
      html: templateHTML.substitute(obj) 
     })); 
    }); 

    // inject all in one go, single dom access 
    parentTable.appendChild(fragment); 
})(); 

驚異的なマージン対ファイアフォックスとie9によるクロムの勝利。また、驚くべきことに、firefox個々の注射では断片よりも速い。おそらくボトルネックは、それは常にdodgyされているテーブルのTRであるということです。

テンプレート用:mustacheやunderscore.jsなどのテンプレートを使用して見ることもできます。

+0

ありがとう、それは良いアドバイスです。私は間違いなくこのように物事をスピードアップすることができます。 私はJSでページ全体を構築するアプローチはクライアントに集中しすぎると思いますが、私たちはIE7をサポートしなければならず、ユーザーもコンピュータの速度が遅くなる可能性があります。いくつかのJSPタグを使用してページに開始データを入力してから、同じタグを使用して新しいエントリをコピーできるテンプレートを作成します。 –

2

私は100%確信していませんが、問題はdomツリーの索引付けにあると私に聞こえます。

まず第一に、あなたはIDを使用しなければならないか、またはあなたは、クラスで管理することができますか? IDの置き換えが主な問題だと言うからです。

はまた、なぜあなたはちょうど新しいHTMLを挿入するのではなく、DOMツリーの一部のクローンを作成するのですか?

var template = '<div id="{ID}" class="{CLASSES}">{CONTENT}</div>'; 
template.substitute({ID: "id1", CLASSES: "c1 c2", CONTENT: "this is the content" }); 

あなただけその文字列を取り、内部のhtmlとしてそれを入れ、次にここにhttp://mootools.net/docs/core/Types/String#String:substitute

それについての詳細を読むことができます:(MooToolsはを使用している場合) あなたはそうのように、文字列の代替方法を使用することができますコンテナは、のは言わせて:

$("container_id").set("html", template); 

私はそれをクローンし、再度インデックスそれを、私は確認することはできませんがないので、それは効率を向上させるかもしれないと思います。それを行って何が起こるか見る。

関連する問題