プロが教える店舗&オフィスのセキュリティ対策術

jQueryのappendの中身の出力について、ご教授頂きたく投稿いたします。
大変恐縮ですが、どなたかご教授頂けると幸いです。

data.js(中身は下記をご参照下さい)というデータが格納されたJSから、
appendを使ってデータを出力しています。


appendの数を減らすため、下記のようにJSを変更してみたのですが、
出力されたデータが[object object]となってしまい、きちんと表示されなくなってしまいました。

どのようにしたら変更後のJSでも出力されるようになるか、
ご教授いただけないでしょうか?
※data.jsはシステム上、中身を変更・修正することが出来ません。


------------------------------------------------------------------------
変更前のJS
------------------------------------------------------------------------

$("#common")
.append($("<ul>")
.append($("<li>").addClass("news1").append(commonData.headerAnchorHtml("ニュースデータ1")))
.append($("<li>").addClass("news2").append(commonData.headerAnchorHtml("ニュースデータ2")))
.append($("<li>").addClass("news3").append(commonData.headerAnchorHtml("ニュースデータ3")))
)
)




------------------------------------------------------------------------
変更後のJS
------------------------------------------------------------------------

var $common = '';

$common += '<ul>';
$common += '<li class="news1">'+ tgrCommon.headerAnchorHtml("ニュースデータ1") +'</li>';
$common += '<li class="news2">'+ tgrCommon.headerAnchorHtml("ニュースデータ2") +'</li>';
$common += '<li class="news3">'+ tgrCommon.headerAnchorHtml("ニュースデータ3") +'</li>';
$common += '</ul>';



$("#common").append($common);


------------------------------------------------------------------------
data.jsの中身
------------------------------------------------------------------------

//データ
var commonData = {};
(function () {
var menuAnchorObject = {
"ニュースデータ1" :{"href":"リンク先1", "id":"", "css":"", "target":""},
"ニュースデータ2" :{"href":"リンク先2", "id":"", "css":"", "target":""},
"ニュースデータ3" :{"href":"リンク先3", "id":"", "css":"", "target":""},



};


//アンカー
commonData.headerAnchorHtml = function (name) {
return menuAnchorHtml(name, true);
};
commonData.footerAnchorHtml = function (name) {
return menuAnchorHtml(name, false);
};
function menuAnchorHtml(name, scFlg) {
var aObj = menuAnchorObject[name];
if(aObj === undefined) {
aObj = {};
}
var $anchor = $("<a>").attr("href", aObj.href).html(name);

if (aObj.id) {
$anchor.attr("id", aObj.id);
}
if (aObj.css) {
$anchor.addClass(aObj.css);
}
if (aObj.target) {
$anchor.attr("target", aObj.target);
}
if (scFlg && aObj.sc) {
$anchor.on("click", function() {
sc(aObj.sc);
});
}
return $anchor;
}



//URL置換
commonData.replaceQuery = function (repUrl, addParam) {
if(repUrl === "" || addParam === ""){
return repUrl;
}
if(repUrl.indexOf("#") != -1){
addParam += "#" + repUrl.split("#")[1];
repUrl = repUrl.split("#")[0];
}
return (repUrl.indexOf("?") != -1) ? repUrl+"&"+addParam : repUrl+"?"+addParam ;
}


})();
------------------------------------------------------------------------

質問者からの補足コメント

  • HAPPY

    yambejp 様

    早々のご回答、誠にありがとうございました!
    重ねてのお願いで大変恐縮ですが、もう少し具体的に教えていただくことは可能でしょうか?
    お手数おかけしますが、何卒よろしくお願い致します。

    No.1の回答に寄せられた補足コメントです。 補足日時:2017/01/30 14:23
  • HAPPY

    fujilin 様

    早々のご回答、誠にありがとうございました!

    ご指摘の通り、

    tgrCommon 誤
    commonData 正

    となります。大変失礼致しました。


    '<li class="news1">'+ '[object object]' +'</li>';
    として評価されているものと推測します。
    実行後を調べてみれば、UL要素やLI要素は意図通りにappendされているのではないかと思います。

    こちらもおっしゃられる通りでulやliはappendされております。


    多分、tgrCommon.~~()の関数部分をHTMLテキストを返すように修正すれば、意図通りに動作するのではないでしょうか。


    大変恐縮ですが、こちらをもう少し具体的に教えていただくことは可能でしょうか?
    重ねてお手数お掛けいたしますが、何卒よろしくお願い致します。

    No.2の回答に寄せられた補足コメントです。 補足日時:2017/01/30 15:15
  • HAPPY

    fujillin 様

    大変ご丁寧な回答を頂き、誠にありがとうございました。
    頂いた方法でいくつか試してみたいと思います。

    > ところで、jQueryは本来、jQueryオブジェクトを利用することで、頻出する記述を簡略化できるように考えられていると思いますが、なぜわざわざテキストベースに戻したいのでしょうか?
    > 目的がよくわかりませんね。


    今回jQueryを軽くするという目的で、上記のように変更を行う予定でした。

    上記は抜粋ですが、実際は.appendが200回以上出てくるので、
    DOM要素の操作を少なくする(=appendを減らす)と軽くなるのでは・・・という思いからです。

    質問の内容からは少しそれてしまいますが、
    fujillin 様から頂いた方法などを拝見するに、
    元にままでも重くはない、ということでしょうか?

    ご回答頂ければ幸いです。

    No.3の回答に寄せられた補足コメントです。 補足日時:2017/01/30 18:47

A 回答 (4件)

ANo3です



>今回jQueryを軽くするという目的で、
>上記のように変更を行う予定でした。
何が重いのでしょうね?
多分、以下のどちらかと思いますが。
1)jQueryを読み込む分が重い
2)スクリプトの処理に時間がかかり重く感じる

1)に関しては、読み込まなければその分は軽くなるのは当然ですが、ご呈示のdata.js(←変更不可)がすでにjQueryを前提にしているようですので、やめるわけにいかないと推測します。
また、jQuery自体もせいぜい二百数十kb程度(ミニマイズすると100kb以下)ですので、最近の通信環境から考えればこれを重たいとは言わないように思います。

2)に関しては、確かにjQueryを利用すると処理の記述は簡単になりますが、実行時はそれをjQueryが解釈して素のjavascriptで実行するという手間がかかりますので、理論的には素のスクリプトの方が速くなるはずです。
一方で、jQueryはそれなりの専門家達が処理速度も考慮しながらバージョンを重ねてきていますので、例えば、私が素のスクリプトで作成しても(要領が悪いので)必ず速くなるとは言い切れません。

>DOM要素の操作を少なくする(=appendを減らす)と軽くなるのでは・・・という思いからです。
確かにDOMを操作する際に、個々に順次追加してゆくよりもDocumentFragmentを利用して、生成した要素を一旦Fragmentに追加しておいてから、最後にまとめてDOM要素に追加する方が効率が良いという情報があったような気がします。(実際の差がどの程度かは知りません)

>元にままでも重くはない、ということでしょうか?
逆に、質問者様の環境では「元のままでは重くて、改善が必要」という状況なのでしょうか?

試しに、下記のようなスクリプトで簡単に比較してみました。
実際には、記述の方法や使用するメソッドによっても変わると思いますし、実行環境によっても処理時間は変わるので、非常に大雑把な比較と言えます。
3000回繰り返してLI要素を生成・追加していますが、私の環境では
 native = 292
 jQuery = 742
となり、確かにjQueryのほうが2倍以上の時間がかかっていることになります。
ただし、タグテキストによる生成ではなく、createElement、appendChildを利用した場合との比較ですが。
でも、実際の差で見てみると(3000回で)0.4秒程度の差ですので、これに類する程度の処理内容であれば、人間の感覚からするとほとんど差がないといっても良さそうな気もしますが・・・?

同様に、文字列操作やHTMLタグテキストでの追加と、通常のappendChildでの追加の場合での速度比較などもなさってみると良いのかもしれませんね。


// ***** テストサンプル *****
var count = 3000, i;
var t1 = new Date();

//*** nativeでの要素追加処理 ***
var ul = document.createElement("ul");
document.getElementById("common").appendChild(ul);
for(i=0; i<count; i++){
var li = document.createElement("li");
li.appendChild(document.createTextNode("test string1"));
ul.appendChild(li);
}

var t2 = new Date();
console.log( "native = " + (t2-t1));

//*** jQeryでの要素追加処理 ***
ul = $("<ul>").appendTo($("#common"));
for(i=0; i<count; i++){
$("<li>").html("test string2").appendTo(ul);
}

t1 = new Date();
console.log("jQuery = " + (t1-t2));
    • good
    • 0
この回答へのお礼

fujillin 様

大変ご丁寧な回答を頂き、重ねて誠にありがとうございました。

> 逆に、質問者様の環境では「元のままでは重くて、改善が必要」という状況なのでしょうか?

このスクリプトだけではないのですが「サイト全体が重く改善が必要」だったので、
その一環として今回の質問の作業に至った次第です。


また実験も行って頂きありがとうございます!
私の環境でも頂いた方法と元の方法とを比較して実験してみました。

若干ですが今回教えていただいた方法を使った「最後にまとめてDOM要素に追加」のほうが軽くなったのですが、
これから何度か実験と比較を重ねながら実装につなげたいと思います。

繰り返しにはなりますが、何度も質問→大変ご丁寧な回答を頂き、本当にありがとうございました!

お礼日時:2017/02/05 23:28

ANo2です



>こちらをもう少し具体的に~~
ANo1様の回答にもあるように、通常のHTMLタグと同様にテキストを返せばよいです。
基本となる部分は、
 var anchor = "<a href='" + aObj.href +"'>" + name + "</a>";
のような要領ですが、タグ属性のidやcss、target等も設定しているようですので、その部分も加えてあげる必要があります。

・・・と思ったら、
>data.jsはシステム上、中身を変更・修正することが出来ません。
とのことですので、その条件だと外部から参照可能なのはcommonDataオブジェクトだけですね。
そうすると、commonDataに新しいメソッドを追加するなどといった小細工が必要になりそうです。
段々面倒でややこしいことになりますので、処理内容としては本末転倒にはなってしまいますが、一旦、現状のオブジェクトをそのまま受け取って、
 commonData.headerAnchorHtml(~~).get(0).outerHTML
のようにすることでも、大抵のブラウザならHTMLテキストに変換できると思います。


ところで、jQueryは本来、jQueryオブジェクトを利用することで、頻出する記述を簡略化できるように考えられていると思いますが、なぜわざわざテキストベースに戻したいのでしょうか?
>appendの数を減らすため、~~
とは書かれていますが、目的がよくわかりませんね。
もしも、現状の記述方法だとappendのネストがわかりにくいからとか、同じ記述の繰り返しが多いからというのが理由だとするなら、jQueryの機能を利用したままで以下のような解決方法もあると思います。
(オブジェクトの記述も煩雑なら、単なる二次元配列でもよろしいかと)

var items = [
{name:"ニュースデータ1", class:"news1"},
{name:"ニュースデータ2", class:"news2"},
{name:"ニュースデータ3", class:"news3"}
];

var ul = $("<ul>").appendTo($("#common"));

$.each(items, function(){
ul.append($("<li>").addClass(this.class)
.append(commonData.headerAnchorHtml(this.name));
});
この回答への補足あり
    • good
    • 0

こんにちは



jQueryのappendはDOM(オブジェクト)の操作メソッドです。
例えば、
 A.append(B)
では、A、Bとも通常はDOM要素(正確にはDOM要素のjQueryオブジェクト)です。
(試してみたところBはHTMLテキストでも解釈してくれるようです)

変更前の、commonData.headerAnchorHtml("ニュースデータ1")は
 <a href="××" id="○○" ~~>ニュースデータ1</a>
に相当するDOM要素を返します。(HTMLのタグ文字列ではありません)

>出力されたデータが[object object]となってしまい~
一方で、変更後の、tgrCommon.headerAnchorHtml()に関しては、tgrCommonに関係するスクリプト部分が質問文に示されていないため、何を意味しているのかは不明です。
想像するところ、tgrCommon.headerAnchorHtml()はHTMLテキストではなく、commonData.headerAnchorHtml()と同様にDOMオブジェクトまたはjQueryオブジェクトを返しているのではないでしょうか。

このため、
  '<li class="news1">'+ tgrCommon.~~ +'</li>';
の演算で、テキストと連結するためにオブジェクトが文字列化されて、
  '<li class="news1">'+ '[object object]' +'</li>';
として評価されているものと推測します。
実行後を調べてみれば、UL要素やLI要素は意図通りにappendされているのではないかと思います。

多分、tgrCommon.~~()の関数部分をHTMLテキストを返すように修正すれば、意図通りに動作するのではないでしょうか。
この回答への補足あり
    • good
    • 0

追加する対象をテキストでタグになっている形まで整形してから


appendで流し込んでください。
この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!