【ajaxサンプル】js(jQuery)の非同期通信で画面を切り替える方法

f:id:media-gatch:20181202190157j:plain

どうもー・ω・ガッチ(@MediaGatch)です。

jsのajax通信についてサンプル作成しましたので、使ってください。コピペで使えるように作ってます。

jsのajaxを使って画面切り替えをしたい。できれば、応用できるように具体的な解説も欲しい。そんな方へ向けて記事を書いています。

WEBブラウザのゲーム開発を行なっていたので、ajax通信をゴリゴリ使ったコードを作っていましたので、 サンプルや応用のコツは実務のノウハウから生まれたものなのである程度は使えるコードではないかと思います。

記事の内容はこちら

ajaxjQueryの$.ajax()を使う

今回のサンプルでは、jQueryの、$.ajax() を使用します。 最近ではes6のpromiseを使ったり、fetchを使ったものもありますが、jQueryajaxは簡単に実装でき理解しやすいため、これから始める方は制御の流れを覚え流こともできるため、おすすめです。 tutorialとしても良いサンプルになるのではないかと思います。

ajaxのメリットを生かす

サンプルを実装する前に、ajaxのメリットを1つだけ。 なぜajaxを使うのか?も理解しておいて損はないはず!ということで紹介しますね。

通信容量が少ない

何と言っても通信容量が少ないことがメリットです。

WEBサイトの構成はほぼほぼ決まっていて、ヘッダー、フッター、サイドバーは変わらないことが多いですよね。 そこで、変化がある部分だけサーバーからデータをもらって表示させれば早いよね?!というのがajax通信です。不要な部分のデータを送らないので当然通信は早くなります。

みんな、スマホ通信制限と戦っている時代ですので、、、ajax通信することでユーザーにとってもメリットが出てきます。

ajaxのデメリットも知っておく

デメリットも知っておくと、今後使う時に役に立つことがあるかと思います。 デメリットはあることが悪いのではなく、それをどう工夫して無くしていくのかが大きな醍醐味ではないでしょうか?

その辺りは、応用のコツで僕なりの改善をしていますので読んでもらえたら嬉しいです。

jsのコントロールが複雑になりやすい

ajax通信を多くしようとすると、当然jsのコードも多くなります。 そうなると、コードが複雑に絡み合ってスパゲッティーの出来上がりなんてことも発生します。

ここでは、複雑になりやすいんだな。ということを覚えておいてもらえれば大丈夫です。

ajaxサンプル 画面の切り替え

f:id:media-gatch:20181202190856j:plain

サンプルのコードでは、一般的なWEBサイトを想定した作りにしています。 ヘッダー、フッター、メインコンテンツ、サイドバーがあるwebサイトです。

サンプルの構成はこんな感じです。 ajax通信は、ヘッダーのメニューをクリックした際に行うようにしています。

index.html   // ヘッダー、フッター、サイドバーのあるhtml
home.html    // ホーム画面のコンテンツ部分のみのhtml
about.html   // 概要画面のコンテンツ部分のみのhtml
blog.html    // ブログ画面のコンテンツ部分のみのhtml
contact.html // お問い合わせのコンテンツ部分のみのhtml

style.css    // レイアウト用のcss

index-controller.js //ページの管理を行うjs ※Controllerの役割
menu-manager.js     //メニューの制御を行うjs ※Viewの役割
load.js             //ajax通信を行うファイル ※モデルの役割

index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>サンプル</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.css" />
  <link rel="stylesheet" href="./style.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="./load.js"></script>
  <script src="./menu-manager.js"></script>
  <script src="./index-controller.js"></script>
</head>
<body class="body">

<header class="header">
  <div class="wrap">
    <div class="header__site">サンプルhtml</div>
    <nav>
      <ul class="header__menu">
        <li class="header__item"><a href="#" class="header__link js-header-link" data-href="home">HOME</a></li>
        <li class="header__item"><a href="#" class="header__link js-header-link" data-href="about">ABOUT</a></li>
        <li class="header__item"><a href="#" class="header__link js-header-link" data-href="blog">BLOG</a></li>
        <li class="header__item"><a href="#" class="header__link js-header-link" data-href="contact">CONTACT</a></li>
      </ul>
    </nav>
  </div>
</header>

<div class="container">
  <div class="wrap">
    <div class="container__inner">
      <main class="main">
          <div class="main__inner">
            <article id="js-article" class="article">
              メインのコンテンツ
            </article>
          </div>
        </main>
      <aside class="side">
        <div class="side__inner">
          <div class="side__contents">サイドバーのコンテンツ</div>
        </div>
      </aside>
    </div>
  </div>
</div>

<footer class="footer">
  <div class="wrap">
    ガッチサイトサンプル
  </div>
</footer>

</body>
</html>

home.html

※ about.html、blog.html、contact.html内はコンテンツ毎に異なるので、載せていません。

<div class="home">
  ホームのコンテンツ
</div>

style.css

.body{
  display: flex;
  min-height: 100vh;
  flex-direction: column;
  color:#333;
}
.wrap{
  width:1000px;
  margin: 0 auto;
}
.header{
  padding-top:20px;
  background-color: #dfdfdf;
}
.header__site{
  font-size:1.5rem;
  margin-bottom:20px;
  text-align: center;
}
.header__menu{
  display: flex;
  margin:0;
  list-style: none;
}
.header__item{
  flex:1;
  display: block;
  text-align: center;
}
.header__link{
  display: block;
  height: 40px;
  line-height: 40px;
  text-decoration: none;
  color:#333;
}
.header__link:hover{
  background-color: #f3f3f3;
  color:#666;
}
.container{
  flex:1;   
  background-color:#f3f3f3;
}
.container__inner{
  display: flex;  
}
.main{
  flex:1;
  padding:20px 0;
}
.main__inner{
  min-height:calc(100vh - 190px);
  background-color: #fff;
}
.article{
  padding:40px 20px;
}
.side{
  flex-basis: 300px;
  text-align:center;
  padding:20px 0 20px 20px;
}
.side__inner{
  min-height:calc(100vh - 190px);
  background-color:#fff;
}
.side__contents{
  padding:40px 20px;
}
.footer{
  height:40px;
  line-height: 40px;
  text-align:center;
  color:#fff;
  background-color: #000;
}

index-controller.js

$(function(){
  //メニューの初期化
  menuManager();
  //最初の表示のトリガー
  $('[data-href="home"]').trigger("click");
});
var menuManager=function(){
  $(".js-header-link").on({
    "click":function(e){
      var href = $(e.currentTarget).data("href");
      Load(href,changeArticle);
    }
  })
}
var changeArticle=function(data){
  $("#js-article").html(data);
};

load.js

var Load =function(href,doneCallback){
  console.log("Load実行:", href);
  // ajax通信せずのデバック用
  var data='';
  switch(href){
    case "home":
      data='<div class="home">ホームのコンテンツ</div>';
      break;
    case "about":
      data='<div class="about">アバウトのコンテンツ</div>';
      break;
    case "blog":
      data='<div class="blog">ブログのコンテンツ</div>';
      break;
    case "contact":
      data='<div class="contact">コンタクトのコンテンツ</div>';
      break;
    default:
      data='<div class="home">ホームコンテンツ</div>';
  }
  doneCallback(data);
  /*
  $("#js-article").html(data);
  $.ajax({
    url:href,
  })
  //成功したら
  .done(function(data){
    doneCallback(data);
  })
  //失敗したら
  .fail(function(data){
    alert(data);
  });
*/
}

サンプルコードの解説

上記のサンプルは、メニューをクリックしたら対応したコンテンツを、articleタグ以下に表示する。 ということを行なっているものです。

htmlの解説

jsと関係のある、2つだけ解説します。

  • メニューのaタグのクラスにjs専用のクラスを追加する
  <ul class="header__menu">
    <li class="header__item"><a href="#" class="header__link js-header-link" data-href="home">HOME</a></li>
    <li class="header__item"><a href="#" class="header__link js-header-link" data-href="about">ABOUT</a></li>
    <li class="header__item"><a href="#" class="header__link js-header-link" data-href="blog">BLOG</a></li>
    <li class="header__item"><a href="#" class="header__link js-header-link" data-href="contact">CONTACT</a></li>
  </ul>

cssで使用するクラス名と、jsで使用するクラス名を分けることで、jsで使用していることを明確にしています。 また、 js- から始めることでよりわかりやすくしています。

メニュータグについて、もう1つ。
クリックされるaタグのdata属性にdata-hrefを追加し、対象ファイル名を入れることでクリックした時の切り替え先を指定しています。

  • コンテンツ切り替え対象のarticleタグにidをつける
  <article id="js-article" class="article">
    メインのコンテンツ
  </article>

メニュー画面を押しただけでは、どこの表示を切り替えたら良いのか分からないので、指定してあげる必要があります。今回は、メインコンテンツのarticleだったのでページに1つだけのidを使用していますが、クラス名でも問題ありません。

jsの解説

  • index-controller.js
$(function(){
  //メニューの初期化
  menuManager();
  //最初の表示のトリガー
  $('[data-href="home"]').trigger("click");
});

ページの読み込みが完了した際に、実行させる内容を書いています。

サンプルでは、menuManagerの実行と、
最初にhomeのページを表示させるための、homeメニューのクリックをjsで強制的に実行しています。

  • menu-manager.js
  $(".js-header-link").on({
    "click":function(e){
      var href = $(e.currentTarget).data("href");
      Load(href,changeArticle);
    }
  })

メニューのクリックイベントの設定をしています。 クリック後の動作もここで実装します。

  • load.js
var Load =function(href,doneCallback){
  ...
  doneCallback(data);
}

ajax通信のみを制御しています。実行するたびにjQueryajaxを実行し、完了後に引数でもらった関数を実行します。

完了後の実行処理を引数にすることで、load.jsは通信制御のみのファイルとなり、シンプルになります。 今回のサンプルでは1つのファイルで作る方が簡単ですが、大規模サイトの場合はファイルを分けることで 処理の単位を小さくし、複雑に絡み合った制御を作らなくさせることができます。

WEBサイト製作に応用する3つのコツ

ajax通信を実装す祭のコツを3つ紹介します。 複雑になりがちなjsコードをシンプルにし、回収しやすくする工夫を載せています。

ajax通信の制御ファイルを1つだけに

jQueryajax通信は簡単で使いやすいので、いろんなファイルに書いてしまいがちです。 ページのhtml部分や、ページ毎に作成したjsファイルだったり。。。

いろいろなファイルにかくのではなく、通信を制御するファイルを1つに統一し、管理対象を絞るとコードがシンプルになり、改修も楽になります。

具体的には、jQueryajax関数をラップする関数を自作することです。 ajax通信を1回しか使わなようなパターンでは正直、無駄に見えてしまうかもしれません。

ただ、WEBサイトを運営し、大きくなっていくと必ず改修が入りよりユーザーの使い勝手が良い方法を取り入れようとなります。 その際にajax通信は通信容量も少なくなり、スピードも早くなるので採用される確率は格段に上がります。

その未来を見越して先手を売っておくことは、自分も楽になりますのでおすすめです。

サーバーからのレスポンスを定義しておく(APIを決める)

先ほどの話と似てますが、サーバーとの連携の仕様を決めておくことも大切です。 ajax通信では様々なパラメータを送って通信をすることができます。通常のhtmlのフォームのような感じですね。

都度決めるていくと、このページではこの仕様で、違うページではまた別の仕様。。。 わけが分からなくなってしまします。

事前に全てを決めることは難しいですが、ある程度の型を決めておくことをおすすめします。

  • 以下は実際に仕様していたjsonのサンプルです。(サーバーレスポンスのデータ)
{
  //サーバー処理のstatus
  // 200の場合は、ok
  // それ以外は エラー
  status:200,
  //サーバーからのレスポンスデータの格納場所
  data:{
  },
  //エラー発生時のエラーテキスト格納場所
  error:{
  }
}

MVCモデルを意識する

プログラムを勉強しているとよく耳にするMVCモデル。こちらも意識するとシンプルなコードをかけるようになります。 最近では、MVVMモデルだったり様々なモデルのがあるようですが、基本はMVCなのかなと思います。

簡単に話すと、役割毎にファイルも分けましょう。ってことですね。 その役割をどの単位で分けるかが難しいんだよってつっこみもありそうですが、、、

僕がよく分ける方法を参考程度に載せておきますので、気になる方はお試しください。

◆M:Model(モデル)
データの処理のみを担当。
htmlの変更などは行わない。
引数を与え一定の答えを返してくれる関数など。
例:ajax通信制御、日付計算、html変換関数など。

◆V:View(ビュー)
htmlに紐づいた制御を担当。
イベントリスナーの設置やhtmlの変更も行う。
例:ポップアップ表示の制御、検索フォームの制御など

◆C:Controller(コントローラー) ページ全体の管理を担当。
ページ毎に必ず1つだけあるファイル。
各モデルやビューファイルを実行する。
例:ページ全体に必要なファイルの実行

まとめ

jsのajaxを使って画面切り替えをしたい。できれば、応用できるように具体的な解説も欲しい。こんな方へ向けた、ajaxのサンプルについて紹介しました。

すぐにでも使えるサンプルを使ったつもりです。ぜひ実際に使って試してもらえたら嬉しいです。

うまくいかないことも多いと思います。むしろ、うまくいかない事しかない!と思っている人が多いのかな。。。 僕もそうでしたからね^^;

ajaxにはいくつも罠が仕掛けられていますので。1つずつ罠を解いて試していけば気づかないうちに自然と使えるようになります。

読んでいただきありがとうございました。ajaxを使ったサンプルの紹介でしたー!