クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

JS多次元配列に入れたデータをDOMに入力する(JSON未遂事件簿…)

はじめに、今回はJSONにあまり触れていません!
WordPress等で日々サーバサイドやデータベースの便利さを感じつつ…そういえばJSとよく似たJSON(ジェイソン)というデータ形式があったな。これを使えばクライアントサイドでもグラフやゲームやインタラクティブコンテンツやらを作れそうだ、と思い浮び調べ始めたところ…前提知識不足すぎて知りたいことが数珠つなぎ!数週間も沼にハマってました。*1
未だJSON未到達なのですがw まずはJSの多次元配列でやりたいことを実現してみた。 これを礎に次回こそはJSON体験したひっっ!!

※目次:

※参考:ネイティブJSやってみたシリーズ
qiita.com

HTMLではっぴいえんどのアルバムを入力したった!

まずは手頃なところで、アルバム3枚で解散した「はっぴいえんど」の情報をHTMLで表現。大好きなバンドです。*2

コードはこんなです。

<h1 class="bandname">はっぴいえんど</h1>
<div class="spec">
  <section class="album">
    <h2 class="title">はっぴいえんど</h2>
    <p class="release">1970/8/5</p>
    <ol class="track">
      <li>春よ来い</li>
      <li>かくれんぼ</li>
      <li>しんしんしん</li>
      <li>飛べない空</li>
      <li>敵タナトスを想起せよ!</li> 
      <li>あやか市の動物園</li>
      <li>12月の雨の日</li>
      <li>いらいら</li>
      <li></li>
      <li>はっぴいえんど</li>
      <li>続はっぴ-いいえ-んど</li>
    </ol>  
  </section>

  <section class="album">
    <h2 class="title">風街ろまん</h2>
    <p class="release">1971/11/20</p>
    <ol class="track">
      <li>抱きしめたい</li>
      <li>空いろのくれよん</li>
      <li>風をあつめて</li>
      <li>暗闇坂むささび変化</li>
      <li>はいからはくち</li>
      <li>はいから・びゅーちふる</li>
      <li>夏なんです</li>
      <li>花いちもんめ</li>
      <li>あしたてんきになあれ</li>
      <li>颱風</li>
      <li>春らんまん</li>
      <li>愛餓を</li>
    </ol>  
  </section>

  <section class="album">
    <h2 class="title">HAPPY END</h2>
    <p class="release">1973/2/25</p>
    <ol class="track">
      <li>風来坊</li>
      <li>氷雨月のスケッチ</li>
      <li>明日あたりはきっと春</li>
      <li>無風状態</li>
      <li>さよなら通り3番地</li>
      <li>相合傘</li>
      <li>田舎道</li>
      <li>外はいい天気</li>
      <li>さよならアメリカさよならニッポン</li>
    </ol>  
  </section>
</div>

※参考:【HTMLの基本】書ける前に読む!HTML、CSS、JSの書式-2 - クモのようにコツコツと

これ、3枚だからまだそんなに苦にならないけど、例えばビートルズ*3の全アルバムの場合は十数枚あるんでもっとキツそうです。ホワイトアルバムなんて2枚組ですからね。。
HTMLの何がきついって<li>曲名</li>を複製して、両サイドのタグを間違えて消さないように気を使いながら文字をペーストすることですよね!!

配列、連想配列、多次元配列

この曲名をJSの配列に移してみましょう。配列はナンバリングでアクセスする「配列」とキー名でアクセスする「連想配列」の2種類がありますね。

※参考:配列とは
【JSの基本-前編】書ける前に読む!HTML、CSS、JSの書式-4 - クモのようにコツコツと

//配列
var 配列名 = [値, 値, 値];
//アクセス
配列名[0]

//連想配列
var 連想配列名 = {キー: 値, キー: 値, キー: 値};
//アクセス
連想配列名[キー]

配列は[]カッコ、連想配列は{}カッコです。配列のカウントは1ではなく0から始まります。[0]は1番目という意味。

配列の中に配列を入れ子できて、これを「多次元配列」と言います。

//多次元配列
var 配列名 = [
    値, 
    [値, 値, 値], 
    値
];
//アクセス
配列名[1][0]

2番目のキーの中の1番目のキーの値にアクセス。エクセルでいう「行」と「列」みたいなイメージです。

連想配列の場合はこうなります。

//多次元連想配列
var 連想配列名 = {
    キー: 値, 
    キー: {
        キー: 値, キー: 値, キー: 値
     }, 
    キー: 値
};
//アクセス
連想配列名[キー][キー]

これもキーの中の連想配列のキーの値にアクセス。

また、配列と連想配列の混合もできます。

//多次元配列(混合)
var 配列名 = [
    値, 
    {キー: 値, キー: 値, キー: 値},
    値
];
//アクセス
連想配列名[1][キー]

配列2番目の中のキーの値にアクセス。

多次元配列にはっぴいえんどのアルバム情報を入れる

1枚目のアルバムはこのようになります。
最初のHTMLに比べるもタグが無いため、見た目がスッキリ。修正もしやすそうです。

//アルバムデータ
var album1 = {
  title: "はっぴいえんど",
  release: "1970/8/5",
  track: [
    "春よ来い",
    "かくれんぼ",
    "しんしんしん",
    "飛べない空",
    "敵タナトスを想起せよ!",
    "あやか市の動物園",
    "12月の雨の日",
    "いらいら",
    "朝",
    "はっぴいえんど",
    "続はっぴ-いいえ-んど"
  ]
}
  • 変数album1の中に連想配列タイトルtitle、発売日release、曲名trackを入れる。
  • 曲名trackの値には配列で11曲の曲名を入れる

HTMLの中身を空にする。

データをすべて配列に写したら、HTML内の情報は空っぽにしてしまいましょう。

<h1 class="bandname">はっぴいえんど</h1>
<div class="spec">
  <section class="album album1">
    <h2 class="title"></h2>
    <p class="release"></p>
    <ol class="track"></ol>  
  </section>
  <section class="album album2">
    <h2 class="title"></h2>
    <p class="release"></p>
    <ol class="track"></ol>  
  </section>
  <section class="album album3">
    <h2 class="title"></h2>
    <p class="release"></p>
    <ol class="track"></ol>  
  </section>
</div>

曲名.trackol要素ですが中のリストliは空にしました。アルバムによって曲数が違うので、曲数分ループしながら追加しようと思います。

配列のデータをDOMに入れる

次に配列データの内容をDOMに入れ込みます。

※参考:DOMとは
【JSの基本-前編】書ける前に読む!HTML、CSS、JSの書式-4 - クモのようにコツコツと

このように書きます。

//曲名(1枚目)
var album1Title = document.querySelector('.album1 .title');
album1Title.innerHTML = album1.title;

//発売日(1枚目)
var album1Release = document.querySelector('.album1 .release');
album1Release.innerHTML = album1.release;

//曲名(1枚目)
var album1Track = document.querySelector('.album1 .track');
//(1枚目の曲数分)
for (var i=0; i < album1.track.length; i++) {
var list = document.createElement('li');
    list.innerHTML= album1.track[i];
    album1Track.appendChild(list);
}
  • 変数album1Title.album1 .titleセレクタを取得し、その中に配列album1titleキーの値を入れる(innerHTML
  • 変数album1Release.album1 . releaseセレクタを取得し、その中に配列album1releaseキーの値を入れる
  • 変数album1Track.album1 . trackセレクタを取得し、その中に配列album1trackキー内の配列数(曲数)分ループ
  • 変数listli要素を作成(createElement ())する。
  • 変数listに配列album1trackキーのi番目の値を入れる
  • リスト(変数list)を 変数album1Trackの最後に追加(appendChild()

※参考:ループ(反復)とは
【JSの基本-後編】書ける前に読む!HTML、CSS、JSの書式-5 - クモのようにコツコツと

でけた!!

「HTML」「JS」タブを切り替えてみてください。HTMLの中身は空っぽなのにJSの配列のアルバム1枚目のデータが表示されていますね!

しかしながら、アルバム2枚目、3枚目を増やすときに、このコードをコピペして、変数名を打ち替えて…ふーむ、この量産はまた冗長の「にほひ」がしてきますね。。ビートルズ全アルバムなんか作ってらんないし、修正が生じたら修正箇所が倍々ゲームです。

各アルバムのデータを一つの配列に統合

まず、アルバムデータ自体も変数album1といちいち番号を打つのは手間です。打ち間違わないよう神経を使うしね。

そこで、全体を配列の中にに入れてみます。外側に全体を包む変数albumsを作り、この中に配列を入れます。

//アルバムデータ
var albums = [ 1枚目内容, 2枚目内容, 3枚目内容]

配列の値一つ一つは連想配列になりますね

//アルバムデータ
var albums = [
    {1枚目:内容, 1枚目:内容, 1枚目:内容}, 
    {2枚目:内容, 2枚目:内容, 2枚目:内容}, 
    {3枚目:内容, 3枚目:内容, 3枚目:内容}, 
] 

全体としてはこうなります。

//アルバムデータ
var albums = [
{ //1枚目
  title: "はっぴいえんど",
  release: "1970/8/5",
  track: [
    "春よ来い",
    "かくれんぼ",
    "しんしんしん",
    "飛べない空",
    "敵タナトスを想起せよ!",
    "あやか市の動物園",
    "12月の雨の日",
    "いらいら",
    "朝",
    "はっぴいえんど",
    "続はっぴ-いいえ-んど"
  ]
},
{ //2枚目
  title: "風街ろまん",
  release: "1971/11/20",
  track: [
    "抱きしめたい",
    "空いろのくれよん",
    "風をあつめて",
    "暗闇坂むささび変化",
    "はいからはくち",
    "はいから・びゅーちふる",
    "夏なんです",
    "花いちもんめ",
    "あしたてんきになあれ",
    "颱風",
    "春らんまん",
    "愛餓を"
  ]
},
{ //3枚目
  title: "HAPPY END",
  release: "1973/2/25",
  track: [
    "風来坊",
    "氷雨月のスケッチ",
    "明日あたりはきっと春",
    "無風状態",
    "さよなら通り3番地",
    "相合傘",
    "田舎道",
    "外はいい天気",
    "さよならアメリカさよならニッポン"
  ]
}
]

これで「i番目のアルバム」と配列数をカウントしながらループ処理ができると良さげです。

HTML上のテンプレも先ほどの曲名リストliの様にループで増やせばいいので1枚分にしちゃいましょう。

<h1 class="bandname">はっぴいえんど</h1>
<div class="spec">
  <section class="album">
    <h2 class="title"></h2>
    <p class="release"></p>
    <ol class="track"></ol>
  </section>
</div>
</section>

さらにコンパクト!

アルバム枚数分ループしながら配列データをDOMに入れる!

まず先ほどのHTMLのテンプレート.album一式をアルバム枚数分-1枚ループして複製したい。 (もともとテンプレが1つあったので、アルバム枚数分だと1つ多くなってしまった)

//外枠アクセス
var spec = document.querySelector('.spec');

//テンプレ複製
//(アルバム枚数-1枚)
for (var i=1; i < albums.length; i++) {
  var clone = spec.firstElementChild.cloneNode(true);
  spec.appendChild(clone);
}
  • 変数spec.specセレクタを取得
  • for文で配列albumsの配列をアルバム枚数-1枚分ループ(変数iのカウントを1から始める)*4
  • 変数cloneに変数specの最初の子要素firstElementChild.albumセレクタ)を複製(cloneNode(true))する*5
  • 変数specに変数cloneを最後に追加する(appendChild()

これでテンプレがアルバムと同じ3つに増えた。

次に繰り返し使うセレクタを変数に入れて取得しよう。 querySelectorAllは複数ある要素を全て取得し、配列に入れる。

//タイトル、発売日、曲名アクセス
var specTitle = document.querySelectorAll('.title');
var specRelease = document.querySelectorAll('.release');
var specTrack = document.querySelectorAll('.track');
  • 変数specTitleにタイトル.titleセレクタを取得
  • 変数specReleaseに発売日. releaseセレクタを取得
  • 変数specTrackに曲名. trackセレクタを取得

この取得は最初のテンプレ複製後に実行しないともともとの1つしかない挙動になったので注意。

最後にDOMにデータを入力。for文のアルバム枚数カウント「i枚目」がカギ!

//アルバムデータ入力(アルバム枚数分)
for (var i=0; i < albums.length; i++) {  
  //タイトル入力
  specTitle[i].innerHTML = albums[i].title;
  //発売日入力
  specRelease[i].innerHTML = albums[i].release;
  //曲名入力(曲数分ループ)
  for(var t=0; t < albums[i].track.length; t++) {
    var list = document.createElement('li');
    list.innerHTML= albums[i].track[t];
   specTrack[i].appendChild(list);        
  }   
}
  • for文で配列albumsの配列数(アルバム数)分ループ
  • タイトル:変数specTitlei番目に配列albumsi番目のtitleキーを入れる(innerHTML
  • 販売日:変数specReleasei番目に配列albumsi番目のreleaseキーを入れる(innerHTML
  • 曲名:for文で配列albumsi番目のtrackキーの配列数(曲数)分ループ。なお、曲数カウントの変数はtにしてみた。
  • 変数listli要素を作成(createElement()
  • 変数listに配列albumsi番目のtrackキーのt番目の値を入れる(innerHTML
  • 変数specTracki番目の最後に変数listのリストを追加(appendChild()

でけた!!!

「HTML」「JS」タブを切り替えてみてください。HTMLの中身は空っぽのままJSの配列のアルバム3枚目までのデータが全部表示されていました!

最後に:配列とJSONはよく似た兄弟

冒頭に触れたJSONですが、こんな書式です。

//多次元配列
var 連想配列名 = {
    キー: 値, 
    キー: {
        キー: 値, キー: 値, キー: 値
     }, 
    キー: 値
};

//JSON
 {
    "キー": 値, 
    "キー": {
        "キー": 値, "キー": 値, "キー": 値
     }, 
    "キー": 値
};

ほとんどJSの配列と一緒じゃないですか!違うのはキー名がタブルコーテーション" "でくくられている部分。ちなみにJSONではシングルコーテーション' 'はNGらしい。
外部ファイルとして独立し、拡張子は.jsonになります。これによってPHPなどのサーバサイドからもアクセスや操作が容易になります。
データにするとHTMLテキストよりも拡張性や再利用性が高まるわけです。

次回は外部JSONファイルとして切り出して、アクセスしてみたく思います!昔からJSONはjQueryならシンプルな書式でアクセスできたようだけど、触る機会はなかった。
そして調べたところ、最近は他にもいろんな書き方が増えてきたようです。どれが一番ベターなのか検証したい。それでは!


※参考:ネイティブJSやってみたシリーズ
qiita.com

*1:本当は13日の金曜日にちなんで投稿しようと思ってたw

*2:関係ないけど学生時代コピーバンドやってました。楽しかったなぁ。松本隆のドラム大好きです。

*3:これも大好きなバンド

*4:0からカウントなので1は2番目の意味

*5:引数trueは孫要素ごと複製する設定