ページ更新ボタンは location.reload() の1行で実装できますが、実務では「スピナー付きの更新アニメーション」「n秒後の自動リロード」「データが変わった部分だけAjaxで再取得」など、様々なパターンが求められます。
この記事でわかること
- location.reload()の基本とハードリロード(キャッシュ無視)の違い
- ローディングスピナー付きの更新ボタン実装
- カウントダウン後にリロードする実装
- n秒ごとに自動でページを更新する実装
- 未保存データがある場合に警告を出してリロードを阻止する方法
- AjaxでページのHTMLを取得して特定エリアだけ更新する方法
1. 基本実装とlocation.reload()の挙動
まず基本の実装から確認します。location.reload() を呼ぶだけでページが再読み込みされます。
<button id="reload-btn">ページを更新する</button>
$(function () {
$('#reload-btn').on('click', function () {
location.reload();
});
});
ソフトリロードとハードリロードの違い
- ソフトリロード(location.reload()): ブラウザのキャッシュを使うことがある。通常のF5リロードと同等。
- ハードリロード(キャッシュ無視): URLに
?t=タイムスタンプを付加してキャッシュを回避する方法が使われます。
// ハードリロード(キャッシュを無視して必ず最新を取得)
$(function () {
$('#hard-reload-btn').on('click', function () {
// URLにタイムスタンプを付けてキャッシュを回避
var url = location.href.split('?')[0] + '?t=' + Date.now();
location.href = url;
});
});
location.reload(true)は非推奨
かつては
かつては
location.reload(true) でハードリロードができましたが、この引数は現在の仕様では非推奨となっており、ブラウザによって動作が異なります。キャッシュを確実に回避したい場合はURLにタイムスタンプを付加する方法を使ってください。2. ローディングスピナー付き更新ボタン
ボタンをクリックした瞬間にスピナーを表示し、リロード中であることをユーザーに伝えます。「更新ボタンを何度も押してしまう」問題も防げます。
<button id="spinner-btn"> <span class="btn-text">データを更新する</span> <span class="btn-spinner" style="display:none;"> ⟳ 更新中...</span> </button>
@keyframes spin {
to { transform: rotate(360deg); }
}
.btn-spinner {
display: inline-block;
animation: spin 0.8s linear infinite;
}
$(function () {
$('#spinner-btn').on('click', function () {
var $btn = $(this);
// ボタンを無効化してスピナーを表示
$btn.prop('disabled', true);
$btn.find('.btn-text').hide();
$btn.find('.btn-spinner').show();
// 少し待ってからリロード(スピナーをユーザーに見せるため)
setTimeout(function () {
location.reload();
}, 300);
});
});
disabled属性で二重クリックを防ぐ
クリック直後に
クリック直後に
prop("disabled", true) でボタンを無効化することで、ユーザーが連続クリックしても複数のリロードが発生しません。ローディング画面の詳細な実装はローディング画面を実装する完全ガイドも参照してください。3. カウントダウン付きリロード
「3秒後に自動で更新されます」のようにカウントダウンを表示してからリロードするパターンです。セッションタイムアウト画面やエラー画面でよく使われます。
<p id="countdown-msg">3秒後にページを更新します...</p> <button id="cancel-reload">キャンセル</button>
$(function () {
var count = 3; // カウントダウン秒数
var timer = null;
var canceled = false;
function tick() {
if (canceled) return;
if (count <= 0) {
location.reload();
return;
}
$('#countdown-msg').text(count + '秒後にページを更新します...');
count--;
timer = setTimeout(tick, 1000);
}
tick(); // カウントダウン開始
// キャンセルボタン
$('#cancel-reload').on('click', function () {
canceled = true;
clearTimeout(timer);
$('#countdown-msg').text('更新をキャンセルしました。');
$(this).prop('disabled', true);
});
});
canceledフラグでキャンセル処理を確実に
clearTimeout(timer) だけでは、tick()が既に実行中の場合にキャンセルできないことがあります。canceled フラグを使うことで、tick()の先頭で確実に処理を止められます。4. n秒ごとに自動更新する
株価・ニュース・スポーツスコアなど、リアルタイムデータをポーリングで定期更新するパターンです。残り時間の表示と手動更新ボタンも組み合わせます。
<div id="data-area"> <!-- ここにリアルタイムデータを表示 --> </div> <button id="manual-refresh">今すぐ更新</button> <span id="auto-refresh-timer"></span>
$(function () {
var INTERVAL = 30000; // 30秒ごとにリロード
// 残り時間を表示しながらカウントダウン
var remaining = INTERVAL / 1000;
var timer = setInterval(function () {
remaining--;
$('#auto-refresh-timer').text('次の更新まで ' + remaining + ' 秒');
if (remaining <= 0) {
location.reload();
}
}, 1000);
// 手動更新ボタンでタイマーリセット
$('#manual-refresh').on('click', function () {
clearInterval(timer);
location.reload();
});
});
ページ全体のリロードはUXを損なう場合がある
ページを丸ごとリロードすると、スクロール位置がリセットされユーザーが入力中のデータも消えます。「一部のデータだけ更新したい」場合は後述のAjax部分更新(セクション6)を検討してください。
ページを丸ごとリロードすると、スクロール位置がリセットされユーザーが入力中のデータも消えます。「一部のデータだけ更新したい」場合は後述のAjax部分更新(セクション6)を検討してください。
5. 未保存データがある場合に警告して離脱を阻止する
フォームに入力中のユーザーが誤ってリロードや離脱をしようとしたとき、確認ダイアログを表示して入力データを守ります。
$(function () {
var isDirty = false; // 未保存の変更があるかどうか
// フォームへの入力で「変更あり」フラグをオン
$('form input, form textarea, form select').on('input change', function () {
isDirty = true;
});
// フォーム送信時は警告しない
$('form').on('submit', function () {
isDirty = false;
});
// リロード・タブ閉じ・URL遷移を検知して警告
$(window).on('beforeunload', function () {
if (isDirty) {
return '入力中のデータが失われます。本当にページを離れますか?';
}
});
// 更新ボタンから手動でリロードする場合
$('#reload-with-check').on('click', function () {
if (isDirty) {
if (!confirm('入力中のデータが失われます。ページを更新しますか?')) {
return; // キャンセル
}
}
isDirty = false; // フラグをリセット
location.reload();
});
});
beforeunloadのメッセージ文は表示されない
現代のブラウザでは
現代のブラウザでは
beforeunload イベントで返す文字列は表示されず、ブラウザ固有の定型メッセージが表示されます。カスタムメッセージを出したい場合は、リロードボタン経由のパターン(コード下部)のようにconfirm() を使ってください。6. AjaxでページのHTML一部を取得して更新する
ページ全体をリロードせず、特定のエリアのコンテンツだけを最新状態に更新するパターンです。スクロール位置を保ったまま、表示中のデータを差し替えられます。
<div id="news-feed"> <!-- 動的に更新されるコンテンツエリア --> <p>記事の一覧がここに表示されます。</p> </div> <button id="fetch-btn">最新の記事を取得する</button> <span id="fetch-status"></span>
$(function () {
$('#fetch-btn').on('click', function () {
var $btn = $(this);
$btn.prop('disabled', true);
$('#fetch-status').text('更新中...');
// 同じURLのHTMLを取得して #news-feed のコンテンツを差し替え
$.ajax({
url: location.href,
type: 'GET',
success: function (html) {
var $newContent = $(html).find('#news-feed').html();
if ($newContent) {
$('#news-feed').html($newContent);
$('#fetch-status').text('更新しました(' + new Date().toLocaleTimeString() + ')');
}
},
error: function () {
$('#fetch-status').text('更新に失敗しました。');
},
complete: function () {
$btn.prop('disabled', false);
}
});
});
});
$.ajax()でページのHTMLを取得して部分置換
$.ajax() で現在のURLのHTMLを取得し、$(html).find("#news-feed").html() で目的のセクションの内容だけを取り出して差し替えます。スクロール位置が保たれ、ページ全体のリロードより高速です。ただし同一オリジン(同じドメイン)のURLにしか使えません。パターン選択の目安まとめ
| 要件 | 推奨パターン |
|---|---|
| シンプルなリロードボタン | セクション1(location.reload()) |
| キャッシュを確実に回避したい | セクション1(URLタイムスタンプ付与) |
| 処理中をユーザーに伝えたい | セクション2(スピナー付きボタン) |
| n秒後に自動でリロード | セクション3(カウントダウン) |
| 定期的に自動更新したい | セクション4(setInterval) |
| 入力中に誤って離脱させない | セクション5(beforeunload) |
| スクロール位置を保ったまま更新 | セクション6(Ajax部分更新) |
まとめ
ページ更新ボタンの実装は location.reload() が基本ですが、ユーザー体験を高めるためにスピナー・カウントダウン・beforeunload・Ajax部分更新などを組み合わせることが重要です。要件に合わせてパターンを選んでください。
関連記事: ローディング画面を実装する完全ガイド / カウントダウンを表示する方法 / アニメーション完全ガイド
よくある質問(FAQ)
Qlocation.reload()とlocation.href = location.hrefの違いは?
A
location.reload() はPOSTリクエスト後でもPOSTを再送信するダイアログが出ることがあります。location.href = location.href はGETリクエストとして扱われるため、POST後の再送信ダイアログが出ません。フォーム送信後の確認ページからリロードする場合は後者が安全です。Qリロード後に特定の場所にスクロールしたいです。
AURLに
#section-id のハッシュを付加してリロードすると、ブラウザが対象要素の位置にスクロールします。location.href = location.pathname + location.search + "#section-id" のように指定してください。Qbeforeunloadが常に表示されて困ります(開発中に)。
A
isDirty フラグを確認してください。コンソールで isDirty = false と実行するか、ページ読み込み時に isDirty を false にするデバッグ用コードを入れると、開発中の確認ダイアログを抑制できます。QsetIntervalでの自動更新をページを離れたときに止めたいです。
A
$(window).on("beforeunload", function() { clearInterval(timer); }) でページ離脱時にタイマーをクリアできます。ただし location.reload() を呼んだ直後はページが破棄されるためタイマーは自動的に止まります。QAjax部分更新でCORSエラーが出ます。
AAjaxリクエストは同一オリジン(同じドメイン・ポート・プロトコル)のURLにしか使えません。別ドメインのコンテンツを取得したい場合はサーバーサイドでプロキシを立てるか、対象サーバーがCORSヘッダー(Access-Control-Allow-Origin)を返す必要があります。