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

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

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

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

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

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

記事の内容はこちら

ajax は jQuery の$.ajax()を使う

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

ajax のメリットを生かす

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

オススメプログラミングスクール
  • SkillHacks : Rubyを学びたい方。動画教材とLINE@による無制限サポート
  • TechAcademy : php/wordpressを学びたい方。現役エンジニアのマンツーマン
  • CodeCamp : Pythonを学びたい方。データサイエンス初級をオンラインで

通信容量が少ない

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

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

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

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

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

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

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

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

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

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

サンプルのコードでは、一般的な 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 通信のみを制御しています。実行するたびに jQuery の ajax を実行し、完了後に引数でもらった関数を実行します。

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 以下は実際に仕様していた json のサンプルです。(サーバーレスポンスのデータ)
{
  //status
  // 200ok
  //  
  "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 を使ったサンプルの紹介でしたー!

オススメプログラミングスクール
  • SkillHacks : Rubyを学びたい方。動画教材とLINE@による無制限サポート
  • TechAcademy : php/wordpressを学びたい方。現役エンジニアのマンツーマン
  • CodeCamp : Pythonを学びたい方。データサイエンス初級をオンラインで

関連の記事を読んでみる