スクリーンショット_2019-08-05_23

#xhack勉強会 レポ 「【池袋開催】JavaScriptと無料APIを駆使してウェブアプリ開発ハンズオン 」(2019年7月20日)

全くの未経験からプログラミング学習を初めて約3ヶ月になります。

先日参加した #xhack勉強会 の内容をまとめてみました。

以前参加した際のレポ↓↓


こちら、本勉強会のConnpassページのリンクです。↓


■本勉強会の目的


JavaScriptとwebAPI(今回はぐるなびAPI。無料)を使って、こんなの↓↓↓を作りたい


なんかこれだけでめちゃめちゃwebサービスっぽくなる!
APIを使えば、JavaScriptだけでこんなのが作れちゃうみたい。

楽しみです!


■APIとは

詳細知りたい方はググってもらえればと思いますが、

アプリケーション・プログラミング・インターフェース の略で、
別のソフトウェアの機能を利用する仕組み。
要求と応答を事前に決めておく

(資料の言葉丸パクリ)

そんなもののようです。



■WebAPIとは


こちらも詳細はGoogle先生にお任せしますが、

クライアント(ブラウザを表示するPCやスマホ)から
サーバー(インターネットに接続されたコンピュータ)へデータを要求し、サーバーからクライアントへデータを返す。

Web上で動くAPIってことね!と雑に理解。

今回使うぐるなびやTwitter、Amazonなどの企業が提供しているものもあれば、公的機関が提供しているものもある。
自分でも結構簡単に作れちゃうみたい。自作してみようかなー。

■URLとは

WebAPIの要求(リクエスト)はURLベースなので、URLに関する知識が必要となります。

https://www.example.com?〇〇〇=■■■■&〇〇〇〇=■■■■■■

ホスト名  : www
ドメイン名 : example.com
パラメータ : ? 以降がパラメータ

複数パラメータを指定したいときは、&でつなぐ。


■JSONとは

JSON (JavaScript Object Notation)

WebAPIの応答(レスポンス)はいろんなデータ形式(JSON/XML/CSVなど)がありますが、今回はJSONです。
データ形式については、#xhack のとよももさんがまとめているわかりやすいやつがあります!


■JSONを書いてみよう

●書き方のルール
 ・{}で囲む
 ・"key":value の形式  
  :で区切る
 ・カンマ `,` で区切る
 ・配列`[]`が使える

obj = {
     "name": "松田 信介",
        "age": 33,
       "items": {
         "car": "BMW X6",
         "book": ["JavaScript", "Ruby", "Sinatra"]
       }}

こんな感じになりますね。


ちなみに、ちゃんとJSONの形式になっているか、ここのサイト↓ で確認できます!


構文正しいパターン↓↓↓


構文間違ってるパターン↓↓↓(一番最後の中括弧を消しました)



■API keyの取得

ぐるなびAPIを使うには、API keyを取得しないといけません。
ここ↓にアクセスして、アカウント発行すればメールでAPI keyが送られてきます。

めちゃめちゃ簡単なので、API key持ってない方もぜひ。



■API テストツール


このページで、取得したAPI keyを使ってテスト的にリクエストを送り、レスポンスを表示させることができます。
( セキュリティ上  keyid の中身を消してますが、本来はここに自分のAPI keyを入れます。)

これは、「freeword」に「焼肉」と入れたときの結果をリクエストしています。


全国のぐるなびの情報から、「焼肉」でヒットしたものだけ(の一部)がJSONデータとして返ってきます。


返ってきたJSONデータをブラウザにそのまま表示させると、こんな感じ。


返ってきたデータの一番最初の部分、

"total_hit_count" : 38041,
"hit_per_page" : 10,
"page_offset" : 1

全部で38041件ヒットしているが、1ページあたり10件表示できる1ページ目だけを取得しているってこと。
検索したときに全データを取得するわけじゃないんですね!


これは、たとえばTwitterのタイムラインで下にスクロールしていったときに、その都度古いデータを取得していくのと同じ原理だそうです。

いちいち全データを取得していたらデータ量が膨大になってしまうので、必要になったら都度取得するということみたいです。
Googleマップでも同様の技術が使われているらしいです。


ここまでで、

・JSONの書き方
・APIでのデータ取得


がなんとなくわかったところで、JavaScriptを使って実装していきます!


■DOMの取得、DOMの動的追加


まずは、練習でこのコードを使っていきます!

<!DOCTYPE html>
<html>
 <head>
   <title>Page Title</title>
 </head>
 <body>
   <!-- ボタン -->
   <a class="button" onclick="addCardItem()">追加</a>
   <!-- リスト -->
   <div id="main-block"></div>
   <script>
     // 親要素を取得
     const mainBlock = document.getElementById("main-block");
     mainBlock.innerHTML = "XHACK";
     console.log(mainBlock);
     // DOMを動的に生成している
     function addCardItem() {
       for (var i = 0; i < 2; i++) {
         let node = document.createElement("div");
         let imgnode = document.createElement("img");
         imgnode.src = "https://grapee.jp/wp-content/uploads/32187_main2.jpg";
         mainBlock.appendChild(node);
         node.appendChild(imgnode);
       }
     }
   </script>
 </body>
</html>


ブラウザで表示すると、「追加」と「XHACK」という文字。

「追加」は、これ↓↓↓

<!-- ボタン -->
<a class="button" onclick="addCardItem()">追加</a>


「XHACK」は、これ↓↓↓

// 親要素を取得
const mainBlock = document.getElementById("main-block");
mainBlock.innerHTML = "XHACK";

DOMを取得し、中身を書き換えてますね。


そして、「追加」はaタグで、onclickイベントaddCardItem()が設定されているので、クリックすると、、、

今回は猫画像を2つだけ表示しています。



appendChild()は、子要素を追加するメソッドです。

処理の流れとしては、

// 親要素を取得
const mainBlock = document.getElementById("main-block");

ここで親要素を取得し、
その子要素にdivタグ、さらにその子要素にimgタグを生成し、imgタグのsrcにネコ画像を指定

ですね。


■Ajax処理実装


とりあえず、ぐるなびAPIを使って簡単なデータ取得をしてみます!

(動画キャプチャをYoutubeにアップしてみました)



 <!-- リスト -->
 <div id="main-block" class="row small-up-1 medium-up-2 large-up-3">
 </div>
 <script>
   // 本来はサーバー側で処理してユーザーからは見えないようにする
   const API_KEY = "ここにAPIkeyを入力"; // apikeyを入力 注意:gitにapikeyを上げないように!!
   const mainBlock = document.getElementById("main-block");
   function loadUrl() {
     let _url = `https://api.gnavi.co.jp/RestSearchAPI/v3/?keyid=${API_KEY}&freeword=焼肉`;
     let xhttp = new XMLHttpRequest();
     // 通信が終わった時の処理
     xhttp.onreadystatechange = function() {
       if (this.readyState == 4 && this.status == 200) 
       {
         let res = JSON.parse(xhttp.responseText);
         var hitcount = res.total_hit_count;
         for (let index = 0; index < res.rest.length; index++) {
           let element = res.rest[index];
           let node = document.createElement("div");
           node.innerHTML = element.name;
           let img = document.createElement("img");
           img.src = element.image_url.shop_image1;
           let anker = document.createElement("a");
           anker.href = element.url;
           anker.innerHTML = element.url;
           
           node.appendChild(img);
           node.appendChild(anker);
           mainBlock.appendChild(node);
         }
       }
     };
     // データ取得開始
     xhttp.open("GET", _url, true);
     xhttp.send();
   }
 </script>

なんか見たことないコードがたくさんでてきた!!!


let xhttp = new XMLHttpRequest();

XMLHttpRequestメソッドを使用すると、Ajax通信ができるようになるらしい。
XMLHttpRequest()で、XMLHttpRequestを初期化する。。。
むずかしい。



// 通信が終わった時の処理
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200)
{

・onreadystatechange

readyState属性が変化するたびに呼び出される。。。


・readyState


onreadystatechange.readyStateプロパティ は、通信の状態を表すようです。
this.readyState == 4 は、通信完了した状態 ですね。


・onreadystatechange.status

onreadystatechange.statusプロパティ は、HTTP状態コードを返します。statusが200なら成功、500ならエラーみたいな、あれです。


ここまでを要約すると、「通信が終わり、かつエラーが出てない場合は〜〜〜(次の処理を行う)」
という意味になります。


・JSON.parse

let res = JSON.parse(xhttp.responseText);


JSONデータを文字列だったりオブジェクトとして操作できるようにするメソッド。



(MDN見れば全部わかる。もはやMDN貼り付けマンと化している。。。)




・XMLHttpRequest.responseText


読んで字のごとく、取得したJSONデータのテキストということ。

let res = JSON.parse(xhttp.responseText);


これで、「取得したJSONデータをJavaScriptで操作できる形に変換し、変数resに格納する」という意味。



var hitcount = res.total_hit_count;
for (let index = 0; index < res.rest.length; index++) {
let element = res.rest[index];
let node = document.createElement("div");
node.innerHTML = element.name;
let img = document.createElement("img");
img.src = element.image_url.shop_image1;
let anker = document.createElement("a");
anker.href = element.url;
anker.innerHTML = element.url;

node.appendChild(img);
node.appendChild(anker);
mainBlock.appendChild(node);

この辺は、さっきやったDOM操作ですね。



// データ取得開始
xhttp.open("GET", _url, true);
xhttp.send();

・XMLHttpRequest.open()



XMLHttpRequest.send()



、、、このへん、ぜんぶ「MDN見てね」状態になってますが、少し自分がMDN読めるようになった今、初学者が要約した内容よりMDNの方が1億倍良質な情報だな!と感じるので、このままMDN推しでいきます笑


知らないこともたくさんでてきましたが、MDN先生が全て導いてくれるので大丈夫ですぅぅぅ〜〜



■入力フォームから検索ワードを取得する


先ほどはJavaScriptコードの中に直接 &freeword=焼肉 と書き、取得した結果を表示しました。
今度は、検索フォームをつくり、そのワードで検索できるようにします。


<!DOCTYPE html>
<html lang="ja">
 <head>
   <meta charset="utf-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title>4th</title>
 </head>
 <body>
   <!-- 検索フォーム -->
   <div class="row">
     <div class="small-2 large-2 columns">検索ワード</div>
     <div class="small-4 large-4 columns">
       <input
         id="search-id"
         class=""
         type="text"
         placeholder="検索ワードを入力してください"
       />
     </div>
     <div class="small-6 large-4 columns">
       <a class="button" onclick="loadUrl()">検索</a>
     </div>
   </div>
   <!-- リスト -->
   <div id="main-block" class="row small-up-1 medium-up-2 large-up-3"></div>
   <script>
     // 本来はサーバー側で処理してユーザーからは見えないようにする
     const API_KEY = "●●●"; // apikeyを入力 注意:gitにapikeyを上げないように!!
     const mainBlock = document.getElementById("main-block");
     var searchData = "";
     function loadUrl() {
       // 全ての子要素を削除する
       while (mainBlock.firstChild)
         mainBlock.removeChild(mainBlock.firstChild);
       // 検索ワードを取得する
       searchData = document.getElementById("search-id").value;
       // URLの生成 本来はサーバー側で処理すべき(apikeyがユーザーに見えてしまうので)
       let _url = `https://api.gnavi.co.jp/RestSearchAPI/v3/?keyid=${API_KEY}&freeword=${searchData}`;
       // Ajax(XMLHttpRequest)処理
       // APIを実行して結果のJSONデータを加工している
       let xhttp = new XMLHttpRequest();
       // 通信が終わった時の処理
       xhttp.onreadystatechange = function() {
         if (this.readyState == 4 && this.status == 200) {
           let res = JSON.parse(xhttp.responseText);
           for (let i = 0; i < res.rest.length; i++) {
             addCardItem(res.rest[i]);
           }
         }
       };
       // データ取得開始
       xhttp.open("GET", _url, true);
       xhttp.send();
     }
     // DOMを動的に生成している
     function addCardItem(item) {
       var node = document.createElement("div");
       node.setAttribute("class", "column");
       var txt =
         `<div class="callout"><a href="">` +
         `<p>${item.name}</p>` +
         `<img src="${item.image_url.shop_image1}" alt="">` +
         `</a></div>`;
       node.innerHTML = txt;
       mainBlock.appendChild(node);
     }
   </script>
 </body>
</html>


基本はさっきとほぼ一緒です。

ちがうのは、

<input id="search-id"
class=""
type="text"
placeholder="検索ワードを入力してください">

この入力フォームの中身を、



// 検索ワードを取得する
searchData = document.getElementById("search-id").value;

ここで取得し、



let _url = `https://api.gnavi.co.jp/RestSearchAPI/v3/?keyid=${API_KEY}&freeword=${searchData}`;

urlパラメータにfreewordとして入れ込む。


これくらいですね。


できたのが、こんな感じ



ぐるなびAPIを使ったサイトの作り方の基本は以上になります!
(後半ただMDN貼り付けただけ!)


あとは、パラメータもfreewordだけでなくたくさんあるので、API仕様を見ながら条件を追加し、オリジナルの検索フォームを作ることもできちゃいます。


今回はあくまで「WebAPIを使ってJavaScriptを実装する」ことがメインなのでCSSは全くいじってませんが、今回のコードの見た目をバッチリ整えれば、それだけでもそれなりになると思います。


■まとめ


実はこの勉強会、3ヶ月ほど前に同じ講座に参加し、今回は復習枠(なんと、無料!)として参加しました。
前回参加した時はプログラミング勉強始めた直後で、ifとかforを覚えたてくらいの実力だったので、前半のDOM操作あたりからついていけなくなりました。

今回3ヶ月ぶりに開催され、さらに無料枠という最高のシステムまで導入されていたので迷わず参加。

実際講義を受けてみて、JS以外のAjax通信の知識も取り入れながらだったので、正直xhackの他のJavaScriptの講座よりも数段難しいと感じました。

このnoteのまとめも、うまくまとまっている自信ありません。。


WebAPI使えたら便利だね〜〜!
てことだけはわかりました。(雑!!!)


あ、あと、開催時期は前後しちゃいましたが、xhack勉強会の「MDNを読もう」のおかげで、以前よりかなりMDNを読めるようになりました。
これはまじですごい能力を身につけたぞぉ!
というような気分になっています。

その時のレポ↓↓↓


勉強会に参加してない人でも、もしかしたら理解できるかもしれない内容になっておりますのでよかったらご一読くださいませ。



この記事が気に入ったら、サポートをしてみませんか?
気軽にクリエイターの支援と、記事のオススメができます!
スキ!わたしもあなたがスキです!!!
28
脇田 慎平 / ブログやってます。→http://blog.kiwatchi.com / 元食品メーカーの製造 (チャーハン職人) ・バイヤー / 自分がプログラミング初学者だったときに欲しかった、「みんなのポートフォリオまとめサイト」をReactで作ります。

こちらでもピックアップされています

X-HACK勉強会参加者
X-HACK勉強会参加者
  • 36本

X-HACK勉強会参加者 #xhack勉強会 #ruby #sinatra #javascript #webサービス #programing

コメントを投稿するには、 ログイン または 会員登録 をする必要があります。