実際には「pjax(pushState + ajax)」というjQueryのプラグインを使っていますが、今回はjQueryとpushStateのみでSPA(シングルページアプリケーション)を実装します。
以前紹介したCSSフレームワーク「Ratchet」は、まさに今回の応用です。
JavaScriptライブラリを使わない理由
SPAと言えば、AngularやReactの他、個人的に今後使いたいと思っているVueなどのJavaScriptのライブラリがたくさんありますが、私のような面倒臭がりには大きな問題があります。
例えば、新しく覚えなければならないことが増えたり、フロントだけでなくサーバー側の処理やレスポンスを変えるなど、今まで作ったものを変更したりするのは真っ平ゴメンです!
今回紹介する方法を使えば、既存のWEBアプリに導入するだけで、SPAに変えることができます。
Ajaxでビューを返して抜き出す
以下の方法なら、いつものHTML、CSS、JavaScript(Ajax)のみで、サーバー側も今まで通り普通にビューを返すだけです。
var content_id = '.content';$(function ($) {
'use strict';
if (window.history && window.history.pushState) {
// click link with pushState
$(document).on('click', 'a:not([href^="#"], [class*="ignore"])', function(e) {
e.preventDefault();
var url = $(this).attr('href');
var title = $(this).attr('title');
history.pushState({url: url, title: title}, title, url);
getAction(url);
});
// form submit with pushState
$(document).on('submit', 'form:not([action^="#"], [class*="ignore"])', function(e) {
e.preventDefault();
var url = $(this).attr('action');
var title = $(this).attr('title');
history.pushState({url: url, title: title}, title, url);
postAction(url);
});
// send get
function getAction(url) {
$.get(url, { push_state: 'true' }, function(data) {
loadContent(data);
})
.fail(function() {
loadError();
});
}
// send post
function postAction(url) {
$.post(url, $("form").serialize(), function(data) {
loadContent(data);
})
.fail(function() {
loadError();
});
}
// content
function loadContent(data) {
var title = $(data).find('title').html();
var content = $(data).find(content_id).html();
$('title').html(title);
$(content_id).html(content);
}
// error
function loadError() {
location.href='/error' // or $(content_id).html('<h1>Error!</h1>');
}
// history back with popState
$(window).on('popstate', function(e) {
getAction(location.pathname);
});
}
});
Ajax + pushState の解説
初期設定
まずは、コンテンツを差し替えたい場所の要素を設定します。
var content_id = ".content";
次に、historyまたはpushStateが使えるブラウザかどうか判定します。
もし使えなければ、普通のWEBサイトとして表示します。
if (window.history && window.history.pushState) {
...
}
画面遷移のイベント
次に、リンク(アンカー)をクリックした時の処理(GET)と、フォームをサブミットした時の処理(POST)を書きます。
// click link with pushState
$(document).on('click', 'a:not([href^="#"], [class*="ignore"])', function(e) {
...
}
// form submit with pushState
$(document).on('submit', 'form:not([action^="#"], [class*="ignore"])', function(e){
...
}
このイベントは、クリックまたはサブミットした際に遷移先のURLが「#」から始まらない、もしくはclassに「ignore」が存在しない場合に発生します。
イベントが発生したら、そのままページ遷移させないように、
e.preventDefault();
でイベントを一旦止め、
var url = $(this).attr('[属性名]');
var title = $(this).attr('title');
history.pushState({url: url, title: title}, title, url);
遷移先のURLやタイトルを取得し、ブラウザのURLを書き換えて履歴(history.pushState)に登録。
最後に、GETの場合は、
getAction(url);
そして、POSTの場合は、
postAction(url);
関数を呼び出します。
GET/POST処理
関数内では、Ajaxの$.get()や$.post()メソッドを呼び出しています。
応答が帰ってきたら、
loadContent(data);
を呼び出し、エラーの場合は、
errorContent(data);
を呼び出します。
コンテンツを読み込む
受っとったHTMLデータから、タイトルとコンテンツを取り出して、
var title = $(data).find('title').html();
var content = $(data).find(content_id).html();
JavaScriptでHTMLを差し替えます。
$('title').html(title);
$(content_id).html(content);
以上です。
ページを遷移する際にフェードイン・フェードアウトを使うともっとアプリらしく見えますね!
あと、アンカーに[target=”_blank”]があった場合も除外した方がいいかも。
まあ、参考サイトのように16行とはなりませんが、GETだけでなくPOSTにも対応した上、かなり軽量だと思います。
一応、GitHubに上げてますので、よかったらどうぞ。
- Original:https://minory.org/simple-jquery-spa.html
- Source:Minory
- Author:管理者