0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptでSPAのようなものを構成する

Posted at

やりたいこと

モダンなJavaScriptフレームワークが行っているようなSPAをJavaScriptのみで似たようなものでもいいから実装したい。(Vue.jsとかReactでいいとかは置いといて)

SPA(Single Page Application)とは

従来のウェブアプリケーションの構造であるMPA(Multi Page Applicaton)では、ページごとにサーバーから新しいHTMLを取得していました。
一方SPAではページ遷移を行わずに動的なコンテンツを表示する仕組みです。
初回のページ読み込み時に必要なデータを取得し、動的にHTMLを更新することで、高速なパフォーマンスと優れた保守性を実現します。

ディレクトリ構成

プロジェクトディレクトリ
        ├── docker-compose.yml  //httpサーバー
        ├── html
        │   ├── index.html  // 表示されるhtmlファイル
        │   ├── pages  // 差し込まれるHTMLファイル
        │   │    ├── index.html
        │   │    ├── About.html
        │   │    ├── Contact.html
        │   │    ├── 404.html
        ├── js
        │   ├── Router.js  //ルーティングファイル

環境構築

C:file上では動かないので最低限でもhttpサーバーを作っておきます。

docker-compose.yml
services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro

表示されるhtmlファイル

htmlディレクトリ直下のindex.htmlを編集します

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title></title>
    <script src="js/Router.js"></script>
  </head>
  <body>
    <nav>
      <a href="/" onclick="route()">Home</a>
      <a href="/About/" onclick="route()">私たちについて</a>
      <a href="/Contact/" onclick="route()">お問い合わせ</a>
    </nav>
    <hr />
    <div id="main-contents"></div>
  </body>
</html>

ルーティングファイル

ルーティングするためのRoute.jsを以下のように実装します。
routesにルートを追加していきます。
・キー = ルートパス
・template = pagesのhtmlファイル
・title = 各ページのタイトル
その他詳細は各所コメントアウトに書いてあります。

Router.js
"use strict";

// ——————————————————————————————————————
// ルートごとのテンプレートファイルとページタイトルを管理
// ——————————————————————————————————————
const routes = {
  "/": { template: "/pages/index.html", title: "Home" },
  "/About/": { template: "/pages/About.html", title: "わたしたちについて"},
  "/Contact/": {template: "/pages/Contact.html", title: "お問い合わせ"},
  404: { template: "/pages/404.html", title: "404"},
};
// ——————————————————————————————————————
// リンククリック時に実行
// ——————————————————————————————————————
function route(event) {
  event = event || window.event;  // eventが未定義ならwindow.eventから取得
  event.preventDefault();   //デフォルトの操作をキャンセル
  // 履歴に追加(タイトルは各自 handleLocation でセットするので第2引数は空文字)
  window.history.pushState({}, "", event.target.href);
  handleLocation();
}
// ——————————————————————————————————————
// ページの描画
// ——————————————————————————————————————
async function handleLocation() {
  const path = window.location.pathname;  // 現在のパスを取得
  const route = routes[path] || routes[404];  // 定義ルートから該当パスを取得。なければ404
  // HTML読み込み
  try {
    const res = await fetch(route.template);  // route.templateからHTMLファイルを取得
    const html = await res.text();  // レスポンスの本文をテキストとして取り出す
    document.getElementById("main-contents").innerHTML = html;  // main-contentsへ本文を追加
  } catch (err) {
    console.error(err);
  }
  document.title = route.title;   // タイトルを書き換え
}
// 履歴操作(popstate/戻る・進)を監視し再描画を行う
window.addEventListener("popstate", handleLocation);
// 初回ロード時の描画
window.addEventListener("DOMContentLoaded", handleLocation);

まとめ

JavaScriptでSPAモドキを構成しました。
作ってみるとフレームワークの素晴らしさがよくわかりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?