JavaScriptで画面遷移を実装する方法 - 基本から実践まで徹底解説
こんにちは、とまだです。
Webサイトでボタンをクリックしても画面が変わらない。 ページの読み込みが遅くてイライラする。
そんな経験はありませんか?
今回は、JavaScriptを使った画面遷移の実装方法について解説します。 基本的な方法から、最新のSPA技術まで幅広くカバーしていきます。
画面遷移とは?なぜJavaScriptで実装するのか
画面遷移について考える前に、普段私たちがWebサイトを使っているときのことを思い出してみてください。
ショッピングサイトで商品を見ていて、詳細ページを開くとき。 SNSでタイムラインから個別の投稿を見るとき。 ニュースサイトで記事一覧から個別記事を読むとき。
これらすべてが「画面遷移」です。
従来の画面遷移の問題点
昔のWebサイトでは、リンクをクリックするたびにページ全体が真っ白になって、新しいページが表示されるまで待つ必要がありました。
これは電車を乗り換えるときに、一度改札を出て、また入り直すような不便さがあります。
特に以下のような問題がありました。
待ち時間のストレス ページが表示されるまでの空白時間は、ユーザーにとって大きなストレスです。特にモバイル環境では、この待ち時間が致命的になることもあります。
状態の喪失 入力途中のフォームデータや、スクロール位置など、ユーザーの操作状態がリセットされてしまいます。
サーバーへの負荷 毎回HTMLファイル全体を送信するため、サーバーにも大きな負荷がかかります。
JavaScriptで画面遷移を実装するメリット
JavaScriptを使うことで、これらの問題を解決できます。
必要な部分だけを更新することで、ユーザーは待ち時間なくスムーズに画面を切り替えられます。まるでスマートフォンのアプリを使っているような、快適な体験を提供できるのです。
さらに、以下のようなメリットもあります。
アニメーション効果の追加 画面がフェードインしたり、スライドしたりする効果を加えることで、より洗練された印象を与えられます。
データの事前読み込み ユーザーがクリックする前に、次のページのデータを先読みしておくことも可能です。
履歴管理の柔軟性 ブラウザの戻るボタンの挙動を細かく制御できます。
基本的な画面遷移の実装方法
location.hrefで別ページへ移動する
まずは最も基本的な方法から始めましょう。
location.href
は、現在のページから別のページへ移動する最もシンプルな方法です。これは、タクシーに乗って目的地を伝えるようなものです。運転手(ブラウザ)に行き先を伝えれば、確実にそこへ連れて行ってくれます。
// ボタンクリックで別ページへ移動
const button = document.getElementById('moveButton');
button.addEventListener('click', () => {
location.href = '/dashboard';
});
このコードは、ボタンがクリックされたときに/dashboard
というページへ移動します。
ただし、この方法には注意点があります。ページ全体がリロードされるため、現在の状態はすべて失われます。フォームに入力していたデータや、JavaScriptで管理していた変数の値なども、すべてリセットされてしまうのです。
そのため、この方法は以下のような場合に適しています。
- ログイン後のダッシュボード画面への移動
- 決済完了後の完了画面への移動
- まったく別のセクションへの移動
location.replace()で履歴を残さない遷移
次に、少し特殊な遷移方法を紹介します。
location.replace()
は、現在のページを新しいページで「置き換える」メソッドです。通常の遷移との違いは、ブラウザの履歴に現在のページが残らないことです。
これは、ホテルのチェックアウトのようなものです。一度部屋を出たら、もうその部屋には戻れません。
// ログアウト後の処理
function logout() {
// セッションをクリア
clearUserSession();
// 履歴を残さずログイン画面へ
location.replace('/login');
}
この方法が有効な場面を具体的に説明します。
ログアウト処理 ユーザーがログアウトした後、戻るボタンで元の画面に戻れてしまうと、セキュリティ上の問題が発生する可能性があります。
リダイレクト処理 古いURLから新しいURLへ永続的に移動する場合、古いURLの履歴を残す必要はありません。
エラーページからの復帰 一時的なエラーページから正常なページへ戻る際、エラーページの履歴を残したくない場合があります。
条件に応じた遷移先の制御
実際の開発では、ユーザーの状態や権限によって遷移先を変える必要があることが多いです。
例えば、ECサイトで考えてみましょう。同じ「マイページ」ボタンをクリックしても、一般会員とプレミアム会員では表示される画面が異なるかもしれません。
// ユーザーの権限に応じて遷移先を変更
function redirectByRole(user) {
if (user.role === 'admin') {
location.href = '/admin';
} else if (user.role === 'manager') {
location.href = '/manager';
} else {
location.href = '/user';
}
}
このような条件分岐を使うことで、きめ細かい画面遷移の制御が可能になります。
ただし、セキュリティ面での注意も必要です。悪意のあるユーザーが、URLを直接操作して不正なページへアクセスしようとする可能性があるからです。
そのため、以下のような安全対策を実装することが重要です。
// 安全な遷移の実装
function safeRedirect(url) {
try {
const urlObj = new URL(url, window.location.origin);
// 同一オリジンのみ許可
if (urlObj.origin === window.location.origin) {
location.href = url;
} else {
console.error('外部URLへの遷移は禁止');
}
} catch (error) {
console.error('無効なURL:', error);
}
}
このコードでは、遷移先のURLが自分のサイト内であることを確認してから遷移を実行しています。これにより、外部サイトへの意図しない遷移を防ぐことができます。
SPA(Single Page Application)での画面遷移
SPAの基本概念と仕組み
ここからは、より高度な画面遷移の方法について説明します。
SPA(Single Page Application)は、その名の通り「単一ページのアプリケーション」です。しかし、これは1ページしかないという意味ではありません。
SPAを理解するには、デパートの例えが分かりやすいでしょう。
従来のWebサイトが、各フロアごとに別の建物になっているデパートだとすると、SPAは1つの大きな建物の中で、エレベーターやエスカレーターで移動するデパートです。建物を出ることなく、すべての売り場を回ることができます。
SPAの特徴は以下の通りです。
高速な画面切り替え 必要な部分だけを更新するため、画面の切り替えが非常に高速です。ユーザーは待ち時間のストレスから解放されます。
スムーズなユーザー体験 画面遷移時にちらつきや空白時間がないため、アプリのような使い心地を実現できます。
状態の保持 JavaScriptの変数やフォームの入力内容など、アプリケーションの状態を保持したまま画面を切り替えられます。
では、実際にシンプルなSPAを実装してみましょう。
// シンプルなSPAの実装
class SimpleSPA {
constructor() {
this.currentPage = 'home';
this.pages = {
home: '<h1>ホーム</h1><p>ようこそ!</p>',
about: '<h1>会社概要</h1><p>私たちについて</p>',
contact: '<h1>お問い合わせ</h1><p>ご連絡ください</p>'
};
}
navigateTo(pageName) {
if (this.pages[pageName]) {
document.getElementById('content').innerHTML = this.pages[pageName];
this.currentPage = pageName;
// URLも更新(リロードなし)
history.pushState({ page: pageName }, '', `/${pageName}`);
}
}
}
このコードでは、pages
オブジェクトに各ページのHTMLを保存しています。navigateTo
メソッドが呼ばれると、指定されたページのHTMLを表示エリアに挿入します。
重要なのは、history.pushState
の部分です。これにより、実際にはページ遷移していないのに、URLが変更され、ブラウザの履歴にも記録されます。ユーザーから見れば、通常のページ遷移と変わりません。
History APIを使った履歴管理
History APIは、ブラウザの履歴を JavaScript から操作するための強力な機能です。
これは、タイムマシンのようなものだと考えてください。過去の状態を記録しておき、必要に応じてその時点に戻ることができます。
History APIの主要なメソッドは以下の3つです。
pushState() 新しい履歴エントリを追加します。本を読み進めるときに、しおりを挟むようなイメージです。
replaceState() 現在の履歴エントリを置き換えます。しおりの位置を移動するような操作です。
popstate イベント ユーザーが戻る・進むボタンを押したときに発生します。しおりを使って前のページに戻るときの動作です。
実際の使用例を見てみましょう。
// 履歴に新しいエントリを追加
function navigateToPage(path, title, data) {
// 履歴に状態を保存
history.pushState(
{ path, title, data }, // 保存するデータ
title, // ページタイトル
path // 新しいURL
);
// ページの内容を更新
document.title = title;
updatePageContent(path, data);
}
// 戻る・進むボタンへの対応
window.addEventListener('popstate', (event) => {
if (event.state) {
// 保存されていた状態を復元
const { path, title, data } = event.state;
document.title = title;
updatePageContent(path, data);
}
});
このコードの重要な点は、pushState
で保存したデータが、popstate
イベントで取得できることです。これにより、単にURLを変更するだけでなく、その時点でのアプリケーションの状態も保存・復元できます。
例えば、検索結果のページで考えてみましょう。ユーザーが検索条件を入力して結果を表示し、その中から1つを選んで詳細ページを見た後、戻るボタンを押したとします。このとき、単にURLを戻すだけでなく、検索条件や結果の一覧も復元できれば、ユーザーは再度検索する必要がありません。
実践的なルーティングシステム
ここまでの知識を組み合わせて、より実践的なルーティングシステムを構築してみましょう。
ルーティングシステムは、URLとページの内容を結びつける交通整理のような役割を果たします。郵便配達員が住所を見て正しい家に手紙を届けるように、ルーターはURLを見て適切なコンテンツを表示します。
実装にあたって、以下の機能を持つルーターを作成します。
- URLパターンとハンドラー関数の登録
- ブラウザの戻る・進むボタンへの対応
- リンククリックの自動処理
- 404エラーページの表示
class Router {
constructor() {
this.routes = new Map();
this.currentRoute = null;
this.init();
}
// ルートを登録
addRoute(path, handler) {
this.routes.set(path, handler);
}
// 初期化処理
init() {
// ブラウザの戻る・進むボタンに対応
window.addEventListener('popstate', (event) => {
this.handlePopState(event);
});
// リンククリックを自動的に処理
document.addEventListener('click', (event) => {
this.handleLinkClick(event);
});
// 現在のURLに対応するページを表示
this.navigate(window.location.pathname, false);
}
// ページ遷移を実行
navigate(path, addToHistory = true) {
const handler = this.routes.get(path);
if (handler) {
// 履歴に追加するかどうかを制御
if (addToHistory) {
history.pushState({ path }, '', path);
}
// ハンドラー関数を実行してページを表示
handler(path);
this.currentRoute = path;
} else {
// 該当するルートがない場合は404ページを表示
this.show404();
}
}
}
このルーターの使い方は非常にシンプルです。
// ルーターのインスタンスを作成
const router = new Router();
// ルートを登録
router.addRoute('/', () => {
document.getElementById('content').innerHTML = '<h1>ホーム</h1>';
});
router.addRoute('/about', () => {
document.getElementById('content').innerHTML = '<h1>会社概要</h1>';
});
このシステムの利点は、新しいページを追加するのが非常に簡単なことです。addRoute
メソッドを呼ぶだけで、新しいルートを追加できます。
また、各ルートのハンドラー関数内で、非同期処理やアニメーションなど、より複雑な処理を実装することも可能です。
フレームワークを使った画面遷移
React Routerの基本
ここまで、純粋なJavaScriptでの実装方法を見てきました。しかし、実際のプロジェクトでは、ReactやVue.jsなどのフレームワークを使うことが多いでしょう。
フレームワークを使う利点は、車を運転するときにカーナビを使うようなものです。目的地までの道順を自分で覚える必要がなく、ナビの指示に従うだけで到着できます。
React Routerは、Reactアプリケーションで最も広く使われているルーティングライブラリです。先ほど実装したルーターの機能を、より洗練された形で提供してくれます。
基本的な使い方を見てみましょう。
import React from "react";
import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
);
}
React Routerの素晴らしい点は、宣言的にルーティングを定義できることです。<Route>
コンポーネントでURLパターンとコンポーネントを結びつけるだけで、自動的にルーティングが機能します。
また、<Link>
コンポーネントを使うことで、通常のアンカータグのような見た目を保ちながら、SPAの高速な画面遷移を実現できます。
Vue RouterやAngular Router
Reactだけでなく、他の主要なフレームワークにも同様のルーティング機能があります。
Vue Router(Vue.js用) Vue.jsの公式ルーターで、Vueコンポーネントとシームレスに統合されています。設定が直感的で、初心者にも扱いやすいのが特徴です。
Angular Router(Angular用) Angularに組み込まれているルーターで、より高度な機能を提供します。ガード機能やモジュール遅延読み込みなど、大規模アプリケーション向けの機能が充実しています。
これらのルーターは、基本的な考え方は同じです。URLとコンポーネントを対応付け、画面遷移時に適切なコンポーネントを表示します。
フレームワークを選ぶ際は、プロジェクトの規模や要件、チームのスキルセットなどを考慮して決定することが重要です。
画面遷移時の注意点とベストプラクティス
パフォーマンスの最適化
画面遷移を実装する上で、パフォーマンスは非常に重要な要素です。
ユーザーは、クリックしてから0.1秒以内に反応がないと「遅い」と感じると言われています。そのため、画面遷移をできるだけ高速化する必要があります。
パフォーマンスを向上させる方法をいくつか紹介します。
必要な部分だけを更新する ページ全体を書き換えるのではなく、変更が必要な部分だけを更新することで、処理時間を大幅に短縮できます。
データの事前読み込み(プリフェッチ) ユーザーがリンクにマウスを乗せた時点で、次のページのデータを先読みしておくことで、実際にクリックされたときの待ち時間を削減できます。
ローディング表示の活用 完全に読み込みが完了するまで待たせるのではなく、スケルトンスクリーンやプログレスバーを表示することで、体感速度を向上させることができます。
// プリフェッチの実装例
async function prefetchPage(url) {
// リンクタグを使ってブラウザに事前読み込みを指示
const link = document.createElement('link');
link.rel = 'prefetch';
link.href = url;
document.head.appendChild(link);
}
// マウスオーバーでプリフェッチを開始
document.querySelectorAll('a[data-prefetch]').forEach(link => {
link.addEventListener('mouseenter', () => {
prefetchPage(link.href);
});
});
このコードでは、data-prefetch
属性を持つリンクにマウスが乗ったときに、自動的にそのページのリソースを先読みします。
セキュリティ対策
画面遷移の実装において、セキュリティは見落とされがちですが、非常に重要な要素です。
特に注意すべきセキュリティリスクを説明します。
オープンリダイレクトの脆弱性 悪意のあるユーザーが、URLパラメータを操作して外部サイトへリダイレクトさせる攻撃です。フィッシングサイトへの誘導に悪用される可能性があります。
XSS(クロスサイトスクリプティング) ユーザーが入力したデータをそのままHTMLとして表示すると、悪意のあるスクリプトが実行される危険があります。
認証状態の不適切な管理 ログインが必要なページへの不正アクセスや、ログアウト後の情報漏洩などのリスクがあります。
これらのリスクに対する対策を実装することが重要です。
// 認証が必要なページへの安全な遷移
async function navigateToProtectedPage(path) {
// まず認証状態を確認
const isAuthenticated = await checkAuth();
if (isAuthenticated) {
// 認証済みの場合のみ遷移
location.href = path;
} else {
// 未認証の場合はログインページへ
// 元のページをパラメータとして保存
location.href = '/login?redirect=' + encodeURIComponent(path);
}
}
このコードでは、保護されたページへアクセスする前に必ず認証状態を確認しています。未認証の場合は、ログインページへリダイレクトし、ログイン後に元のページへ戻れるようにしています。
アクセシビリティへの配慮
最後に、すべてのユーザーが快適に使えるサイトを作るために、アクセシビリティへの配慮も重要です。
画面遷移において特に注意すべき点は以下の通りです。
フォーカス管理 画面が切り替わったとき、キーボードのフォーカスがどこにあるかが重要です。適切な場所にフォーカスを移動させることで、キーボードユーザーの操作性が向上します。
スクリーンリーダーへの通知 視覚障害を持つユーザーは、スクリーンリーダーを使ってWebサイトを利用します。画面が更新されたことを適切に通知する必要があります。
アニメーションの配慮 めまいや吐き気を引き起こす可能性のある激しいアニメーションは避け、必要に応じて無効化できるオプションを提供します。
// 画面遷移後の適切なフォーカス管理
function handlePageTransition(newContent) {
// コンテンツを更新
const mainElement = document.getElementById('main');
mainElement.innerHTML = newContent;
// 新しいページの見出しにフォーカスを移動
const heading = mainElement.querySelector('h1');
if (heading) {
// tabindexを設定してフォーカス可能にする
heading.tabIndex = -1;
heading.focus();
// フォーカスリングを表示しない場合は削除
heading.addEventListener('blur', () => {
heading.removeAttribute('tabindex');
});
}
// スクリーンリーダーに変更を通知
announcePageChange();
}
このような配慮により、より多くのユーザーにとって使いやすいWebサイトを作ることができます。
まとめ
今回は、JavaScriptを使った画面遷移の実装方法について、基礎から応用まで幅広く解説しました。
画面遷移は、Webアプリケーションの基本的な機能ですが、奥が深いテーマでもあります。
ユーザーの立場に立って、どのような画面遷移が最適かを考えながら実装することで、より良いWebサイトを作ることができるでしょう。
ぜひ、今回学んだ知識を活かして、ユーザーフレンドリーな画面遷移を実装してみてください。
著者について

とまだ
フルスタックエンジニア
Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。
著者の詳細を見る →