###実現したいこと
以下の流れでAJAXを使ってHTMLを挿入するのですが、この速度を向上させたいと考えています。
###HTML挿入の流れ
HTML挿入の流れはこうです。
記事一覧にはタイトルとサムネイルが表示されており、それをクリックします。
そのとき通信はせず、まず先にタイトルとサムネイルを表示します。さらにそれ以外の部分の外郭HTMLも表示し、「読み込み中」とします。
そしてAJAXでその他のデータを取得し、できたらその中身を挿入する。という流れです。
###速度の問題
AJAXの前にすでにあるデータを表示したり、外郭のHTMLを表示したりするというのは体感速度を上げる狙いです。
しかしHTMLの挿入速度に問題があります。
上図のように「外郭を先に表示し、データは後で挿入」でなく、「AJAXでの取得が終わったそのときに、データが挿入されたHTMLを表示」とした方が、処理が早いようなのです。
その計測が次のソースコードになります。
###該当のソースコード
ご覧のように「keisoku_1();」と「keisoku_2();」で計測しました。
「keisoku_1();」の方は上図のように「外郭を先に表示し、データは後で挿入」という方法です。
「keisoku_2();」の方は「AJAXでの取得が終わったそのときに、データが挿入されたHTMLを表示」という方法です。
それぞれ実行すると分かるとおり、「keisoku_2();」の方が圧倒的に速いのです。
js
1 2/* 3keisoku_1(); 4外郭のHTMLを取得し、後からデータを入れる方法を計測 5----------------------------------------------*/ 6// 計測を実行 7keisoku_1(); 8function keisoku_1(){ 9 10 var time_before = new Date().getTime(); 11 12 var lis = ''; 13 for ( var i = 0; i < 1000; i++ ) { 14 var data = { num:i, ttl:'hello_'+i }; 15 var html = get_outline_html( i ); 16 var html = update_outline_html( html, data ); 17 lis += html; 18 } 19 $( 'body' ).html( lis ); 20 21 var time_after = new Date().getTime(); 22 console.log( 'keisoku_1() = ' + parseInt(time_after - time_before) ); 23} 24 25// 外郭のHTMLを取得 26function get_outline_html( i ){ 27 return ` 28 <div class="box num${i}"> 29 <p class="ttl"></p> 30 <p class="num"></p> 31 </div>`; 32} 33 34// 後からデータを入れる 35function update_outline_html( html, data ){ 36 var $html = $( html ) 37 .find( '.ttl' ).text( data.ttl ) 38 .find( '.num' ).text( data.num ); 39 return $html[0]; 40} 41 42 43/* 44keisoku_2(); 45データを入れたHTMLを取得する方法を計測 46----------------------------------------------*/ 47// 計測を実行 48keisoku_2(); 49function keisoku_2(){ 50 51 var time_before = new Date().getTime(); 52 53 var lis = ''; 54 for ( var i = 0; i < 1000; i++ ) { 55 var data = { num:i, ttl:'hello_'+i }; 56 var html = get_all_html( i, data ); 57 lis += html; 58 } 59 $( 'body' ).html( lis ); 60 61 var time_after = new Date().getTime(); 62 console.log( 'keisoku_2() = ' + parseInt(time_after - time_before) ); 63} 64 65// データを入れたHTMLを取得 66function get_all_html( i, data ){ 67 return ` 68 <div class="box num${i}"> 69 <p class="ttl">${data.ttl}</p> 70 <p class="num">${data.num}</p> 71 </div>`; 72} 73
###質問
そこで質問ですが、上述した「HTML挿入の流れ」はそのままで、もう一歩速度を向上させられるようなソースコードの工夫などございましたらご教授頂けますでしょうか。
当方JavaScript初心者のため上のソースコードにおかしな点などあるやもしれませんので、もし意図が伝わりにくい等の不備がございましたらどうぞご指摘ください。
以上です。何卒、宜しくお願い申し上げます。
###改善の追記
maisumakun様のアドバイスを受けまして、以下「keisoku_3();」です。
【改善1】として「.clone()」を使い、【改善2】としてクラス付与を変更致しました。
ですが「$html」が取得できないようで、要素の挿入がされない状況になってしまいました。
困ったことにエラーも出ておらず、悪いところがわかりません。
お気づきの点ございましたらご指摘いただければと思い、ここに追記させて頂きました。
js
1 2/* 3keisoku_3(); 4maisumakun様のアドバイスを受けて 5----------------------------------------------*/ 6// 計測を実行 7keisoku_3(); 8function keisoku_3(){ 9 10 var time_before = new Date().getTime(); 11 12 var $html; 13 for ( var i = 0; i < 3; i++ ) { 14 var data = { num:i, ttl:'hello_'+i }; 15 16 if ( i == 0 ){ 17 // 【改善1】1回目だけjQeury化する 18 var html = get_outline_html( '' ); // 【改善2】iを渡してクラス付与しない 19 var $html = $( html ) 20 .find( '.ttl' ).text( data.ttl ) 21 .find( '.num' ).text( data.num ) 22 .find( '.box' ).addClass( 'num'+i ); // 【改善2】ここでクラス付与する 23 }else{ 24 // 【改善1】2回目以降は.clone()する 25 var $html = $html.clone(); 26 $html 27 .find( '.ttl' ).text( data.ttl ) 28 .find( '.num' ).text( data.num ) 29 .find( '.box' ).addClass( 'num'+i ); 30 } 31 $( 'body' ).html( $html[0] ); // $html が取得できていない様子 32 } 33 34 var time_after = new Date().getTime(); 35 console.log( 'keisoku_3() = ' + parseInt(time_after - time_before) ); 36} 37 38
回答2件
あなたの回答
tips
プレビュー