Edited at

初心者目線でAjaxの説明


Ajaxとは

Ajaxとは「Asynchronous JavaScript + XML」の略

Asynchronousとは、非同時性の、非同期の

つまり、「JavaScriptとXMLを使って非同期にサーバとの間の通信を行うこと。」

んん?

詳しく内容を追っていきましょう。


そもそも非同期通信とはどんなものか?

ajax_example.gif

このように画像の遷移のない通信を非同期通信と言います。

同期処理は一瞬画面が白くなって、画面を切り替わることを言います。

こういったことをするためにAjaxという仕組みが必要です。


どうしてこんなことができるのか?

大枠をざっくり先に説明します。


同期通信の場合

webブラウザからサーバーにリクエストを通信し、レスポンスが戻ってくる。

この時に、すべての情報を通信しているので、一瞬画面が白くなる。

=>サーバーからレスポンスが返ってくるまでは他の作業はできない。


非同期通信の場合

webプラウザから一部の情報をリクエストするので、

それ以外の部分は変わらない。なので画面が白くなることがない。

=>サーバーからレスポンスが返ってこなくても他の作業ができる。

ほー

ってことは一部の情報をサーバーに送信して、それを受け取り反映させる仕組みをAjaxっていうんだね。

でもどうやってやっているの?


Ajaxを支える仕組み

ここで登場する技術が


  • XMLHttpRequest

  • JavaScript

  • DOM

  • XML

Ajaxというのは一つの機能でできているのではなく、

複数の機能が組み合わさって実装しています。

それぞれ機能を見ていきましょう


XMLHttpRequest


クライアントとサーバーの間でデータを伝送するための機能をクライアント側で提供する API です。

ページ全体を再読み込みすることなく、URLからデータを読み出す簡単な方法を提供します。

このAPIによって、ユーザの作業を中断させることなくWebページの一部を更新することができます。

(MDNより)


要するに、ブラウザ上でサーバーとHTTP通信を行うためのAPIです。

このAPIを使って実装をするのがJavaScriptです。

でもなんでJavaScriptなの?


JavaScript

それは先程のXMLHttpRequestがjavascriptの組み込みオブジェクトだからです。

組み込みオブジェクトとは、あらかじめ定義されているオブジェクトのことですね。

Ajaxという名前にある通り、非同期通信はjavascriptを使わないと実装できないのです。


DOM


Document Object Model (DOM) は、HTML および XML ドキュメントのための API です。これはドキュメントの構造的な表現を提供し、内容や表示形態の変更を可能にします。端的に言えば、Web ページをスクリプトやプログラミング言語とつなぐような機構です。

(MDNより)


つまり、Ajaxを使って動的なWebページを作成するときに、HTML・XML上のどの要素を変更するかを指定します。そこでDOMはHTMLやXMLを「ツリー構造」として展開し、アプリケーション側に文章の情報を伝え、加工や変更をしやすくするものです。

ツリー構造とは、データ構造の一つで、一つの要素(ノード)が複数の子要素を持ち、一つの子要素が複数の孫要素を持ち、という形で階層が深くなるほど枝分かれしていく構造のこと。

ここで出てくるXMLとはなんなのでしょうか?


XML

Extensible Markup Languageの略。

文書やデータの意味や構造を記述するためのマークアップ言語の一つ(HTMLと似たようなもの)


<?xml version="1.0" encoding="Shift_JIS"?>
<?xml-stylesheet type="text/xsl" href="testxsl.xsl"?>
<おこづかい帳>
 <支出>
  <内容>
   <日付>1月20日</日付>
   <交通費>780</交通費>
   <食費>980</食費>
   <嗜好品>250</嗜好品>
  </内容>
  <内容>
   <日付>1月21日</日付>
   <交通費>950</交通費>
   <食費>1200</食費>
   <嗜好品>300</嗜好品>
  </内容>
  <内容>
   <日付>1月22日</日付>
   <交通費>500</交通費>
   <食費>1500</食費>
   <嗜好品>250</嗜好品>
  </内容>
 </支出>
</おこづかい帳>

XMLはタグを自由に設定でき、そのタグに意味づけをすることができます。

データのやりとりで「XML」を使えば、複数のデータを同時にやりとりしても、どのデータがどの要素なのか一発で判明できます。

ただ現在では、AjaxにはXMLの代わりにJSONという型がよく使われています。

Ajaxという名前にXMLが入っているので、他の型は使えないように思いますが、

そうではないんですね。


Json

JavaScript Object Notationの略。

軽量のデータ交換フォーマットで、人間にとって読み書きが容易で、マシンにとっても簡単にパースや生成を行なえる形式です。

{ "name"   : "John Smith",

"sku" : "20223",
"price" : 23.95,
"shipTo" : { "name" : "Jane Smith",
"address" : "123 Maple Street",
"city" : "Pretendville",
"state" : "NY",
"zip" : "12345" },
"billTo" : { "name" : "John Smith",
"address" : "123 Maple Street",
"city" : "Pretendville",
"state" : "NY",
"zip" : "12345" }
}

現在ではJSONを使用して、非同期通信を行うのが主流となっています。

ん〜

なんだか色々な言葉が出てきたので、まとめて欲しいな〜


まとめ(流れの整理)

ここまで説明してきたものが、どのように関係して、

Ajaxの機能を実装しているかをまとめます。

unnamed.jpg

①ページ上で任意のイベントが発生(ボタンクリックなど)

②JavaScript + XMLHttpRequestでサーバーに対してリクエストを送信(非同期通信)

ほしい情報、返ってくるレスポンスの情報を指定してリクエスト

③サーバーで受け取った情報を処理

サーバーの処理中もクライアントは操作を継続できる

④処理結果をJSONやXMLなどの形式で応答

⑤受診したレスポンスを受けて、DOMでページを更新

更新のあった部分だけを書き換えるため、画像が一瞬白くなることはない。

 

このように機能が結びついてAjax機能を実装しているんですね。


サンプルアプリで動きの確認

abc.gif

文字を入力したらその文字が表示されるアプリを通してAjaxを確認してみます


index.html.erb

<div class="contents">

<%= form_for @todo, html: { class: 'form js-form' } do |f|%>
<%= f.text_field :content, class: 'form__text-field js-form__text-field' %>
<%= f.submit class: 'form__submit js-submit' %>
<% end %>
<ul class="todos">
<%= render @todos %>
</ul>
</div>



_todo.html.erb

<li class="todo"><%= todo.content %></li>



todos.controller.rb

class TodosController < ApplicationController

#indexアクションはTodoの一覧ページとTodoの入力ページを兼ねているので、新しいTodoを作成するためのインスタンスと、テーブルに保存されているTodoを取得します。
def index
@todo = Todo.new
@todos = Todo.order('created_at ASC')
end

#createアクションが呼ばれると何かしらのTodoが入力されていた場合(contentが空でない場合)は、Todoを保存しTodoの一覧ページにリダイレクトします。反対にTodoが入力されていない場合(contentが空の場合)は、Todoの保存はせずに、Todoの一覧ページを再描画します。
def create
@todo = Todo.new(todo_params)
if @todo.save
respond_to do |format|
format.html { redierct_to :root }
format.json { render json: @todo}
end
else
render :index, alert: 'Todoを入力してください'
end
end
#respond_to doを使用し、リクエストされたformatによって処理を分けるようにします。今回はhtmlと非同期通信のためのjsonを扱うようにしました。フォーマットがjsonの時の説明をします。この後jsファイル側で作成したtodo(@todo)を使用するためにrenderメソッドを使用し、作成したtodoをjson形式で返すようにします。

private
def todo_params
params.require(:todo).permit(:content)
end
end



todo.js

$(function() {

function buildHTML(todo) {
//以下はセレクタの中身を新規に作るという意味
var html = $('<li class="todo">').append(todo.content);
return html;
}
//submitイベントを使い、フォーム(js-from)が送信された時に処理が実行されるようにイベントを設定。
$('.js-form').on('submit', function(e) {
e.preventDefault(); //フォームが送信された時に、デフォルトだとフォームを送信するための通信がされてしまうので、preventDefault()を使用してデフォルトのイベントを止めます。
var textField = $('.js-form__text-field'); //class js-form__text-fieldを代入
var todo = textField.val(); //js-form__text-fieldのフォームに入力された値を取得し、todoに代入
//$.ajax関数は、戻り値として XMLHttpRequestオブジェクトを返します。
//ここでサーバーに対しての通信を行う。情報の指定(ここではdataに格納)、送信先、データの型(Json)等を記述
$.ajax({
type: 'POST',
url: '/todos.json',
data: {
todo: {
content: todo
}
},
dataType: 'json' //データをjson形式で飛ばす
})
//↓フォームの送信に成功した場合の処理
.done(function(data) {
var html = buildHTML(data);
$('.todos').append(html); //$.append関数は操作後はDOMに要素が追加された状態になる。
                                                                 //todosクラスに引数で指定したdataのHTML要素を追加。

textField.val(''); //
})
//↓フォームの送信に失敗した場合の処理
.fail(function() {
alert('error');
});
});
});


以上の流れでAjax機能が動いています。

すごい仕組みだな〜