【jQuery】ページ更新ボタンの実装完全ガイド|ハードリロード・カウントダウン・自動更新・Ajax部分更新まで

ページ更新ボタンは 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)を検討してください。

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の違いは?
Alocation.reload() はPOSTリクエスト後でもPOSTを再送信するダイアログが出ることがあります。location.href = location.href はGETリクエストとして扱われるため、POST後の再送信ダイアログが出ません。フォーム送信後の確認ページからリロードする場合は後者が安全です。
Qリロード後に特定の場所にスクロールしたいです。
AURLに #section-id のハッシュを付加してリロードすると、ブラウザが対象要素の位置にスクロールします。location.href = location.pathname + location.search + "#section-id" のように指定してください。
Qbeforeunloadが常に表示されて困ります(開発中に)。
AisDirty フラグを確認してください。コンソールで isDirty = false と実行するか、ページ読み込み時に isDirty を false にするデバッグ用コードを入れると、開発中の確認ダイアログを抑制できます。
QsetIntervalでの自動更新をページを離れたときに止めたいです。
A$(window).on("beforeunload", function() { clearInterval(timer); }) でページ離脱時にタイマーをクリアできます。ただし location.reload() を呼んだ直後はページが破棄されるためタイマーは自動的に止まります。
QAjax部分更新でCORSエラーが出ます。
AAjaxリクエストは同一オリジン(同じドメイン・ポート・プロトコル)のURLにしか使えません。別ドメインのコンテンツを取得したい場合はサーバーサイドでプロキシを立てるか、対象サーバーがCORSヘッダー(Access-Control-Allow-Origin)を返す必要があります。