LoginSignup
20
15

More than 5 years have passed since last update.

PRGパターンとHistory APIを使った画面遷移について

Posted at

概要

登録処理でPRGパターンを使う場合と使わない場合の画面遷移の挙動を検証したときの記録です。
検証で使用したWebアプリケーションはJavaのSpring Bootで開発したものです。

検証パターン

  1. PRGパターンを使う場合
  2. PRGパターンを使わない場合
  3. PRGパターンを使わない + History APIを使う場合

環境

  • Windows10 Professional
  • Java 1.8.0_101
  • Spring Boot 1.4.1
  • Chrome 54
  • jQuery 1.12

参考

1. PRGパターンを使う場合

下図の「RPGパターンを使う」ときの画面遷移の挙動を確認します。

画面補足

  • [A] /index TOPページ
  • [B] /entry 登録フォームページ
  • [C] /regist 登録処理 (画面なし)、処理後に[D]へリダイレクト
  • [D] /result 登録結果ページ
  • [E] /other 他のページ

確認のポイント

  1. [D] /resultから戻るボタンを押したときの遷移先について
  2. [D] /resultでページ再読み込みを行った後に戻るボタンを押したときの遷移先について
  3. [E] /otherから戻るボタンを押したときの遷移先について
PRGパターンを使う場合の遷移図

                  .....................................................................
                  .                                                                   .
  [A]             .   [B]                    [C]                        [D]           .     [E]
  /index          .   /entry                 /regist                    /result       .     /other
 +-----------+    .  +-------------+        +--------------+ REDIRECT  +-----------+  .    +-----------+
 | Index     |  GET  | Entry Form  |  POST  | Registration |  / GET    | Result    |  GET  | Other     |
 | (Page)    |------>| (Page)      |------->|              |---------->| (Page)    |------>| (Page)    |
 |           |    .  |             |        |              |           |           |  .    |           |
 +-----------+    .  +-------------+        +--------------+           +-----------+  .    +-----------+
                  .             ^                                         |    ^      .             |
                  .             |                                         |    |      .             |
                  .             +--------------[Browser back]<------------+    +---[Browser back]<--+
                  .                                                                   .
                  .....................................................................
                   PRG pattern


AddressバーのURL
  [A]-----------------[B]--------------------[C]------------------------[D]-----------------[E]
  /index              /entry                                            /result             /other

スタックされたHistory
  [A]---------------->[B]------------------->[C]----------------------->[D]---------------->[E]
                      /index                                            /entry              /result
                                                                        /index              /entry
                                                                                            /index

動作確認の結果

  • [D] /resultへ遷移すると、historyに[B] /entryと、[A] /indexが記録されている。
  • [D] /resultからブラウザの戻るボタンで戻ると[B] /entryへ遷移する。 ([B] /entryへのGETリクエストは発生しない)
  • [D] /resultでページ再読み込みをしてもhistoryは変わらない。 ([D] /resultへのGETリクエストが発生する)
  • [E] /otherからブラウザの戻るボタンで戻ると[D] /resultへ遷移する。 ([D] /resultへのGETリクエストは発生しない)

この画面遷移の問題点

  • [D] /resultからブラウザの戻るボタンで[B] /entryへ戻り、再度フォームをサブミットすることができてしまう。
    • 対策として登録処理で2重登録のチェック処理の実装、登録時にワンタイムトークンを使用する。(PRGパターンの問題ではありません)
  • [C] /registから[D] /resultへリダイレクトする際にflash scopeを使ってメッセージを渡す場合、[D] /resultでページ再読み込みをするとそのメッセージが失われる。

動作確認の結果 (Chromeのdevtoolsでキャッシュを無効化した状態)

赤字のところは上記のキャッシュが有効化されている場合との相違点です。

  • [D] /resultへ遷移すると、historyに[B] /entryと、[A] /indexが記録されている。
  • [D] /resultからブラウザの戻るボタンで戻ると[B] /entryへ遷移する。 ([B] /entryへのGETリクエストが発生する)
  • [D] /resultでページ再読み込みをしてもhistoryは変わらない。 ([D] /resultへのGETリクエストが発生する)
  • [E] /otherからブラウザの戻るボタンで戻ると[D] /resultへ遷移する。 ([D] /resultへのGETリクエストが発生する)

この画面遷移の問題点

  • [D] /resultからブラウザの戻るボタンで[B] /entryへ戻り、再度フォームをサブミットすることができてしまう。
    • 対策として登録処理で2重登録のチェック処理の実装する。(PRGパターンの問題ではありません)
    • [B] /entryが再読み込みされるのでワンタイムトークンの実装は有効ではない。
  • [C] /registから[D] /resultへリダイレクトする際にflash scopeを使ってメッセージを渡す場合、[D] /resultでページ再読み込みをするとそのメッセージが失われる。

検証用のコード

Form

RedirectForm
public class RedirectForm implements Serializable {
  private static final long serialVersionUID = -2487350655211970792L;
  private String name;
  private String email;

  ...getter/setter省略...

  @Override
  public String toString() {
    return "RedirectForm [name=" + name + ", email=" + email + "]";
  }
}

Controller

RedirectController
@Controller
@RequestMapping(value = "/redirect")
public class RedirectController {

  @RequestMapping(value = "/entry", method = RequestMethod.GET)
  public String entry(Model model) {
    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect/entry";
  }

  @RequestMapping(value = "/regist", method = RequestMethod.POST)
  public String regist(RedirectForm form, RedirectAttributes attributes) {

    // ここはformの内容をDBに登録する処理
    // 登録IDを取得(みなし)
    String id = UUID.randomUUID().toString();
    // 登録メッセージ
    attributes.addFlashAttribute("message", "登録完了");

    return "redirect:/redirect/result/" + id;
  }

  @RequestMapping(value = "/result/{id}", method = RequestMethod.GET)
  public String result(@PathVariable("id") String id, Model model) {

    // ここはIDから登録内容を検索する処理
    // 検索結果をmodelにセット
    model.addAttribute("name", "rubytomato");
    model.addAttribute("email", "rubytomato@example.com");

    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect/result";
  }

  @RequestMapping(value = "/other", method = RequestMethod.GET)
  public String other(Model model) {
    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect/other";
  }

}

Template

index.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <ul>
          <li><a href="/redirect/entry">redirect [A] entry</a></li>
          <li><a href="/redirect2/entry">redirect2 [A] entry</a></li>
          <li><a href="/redirect3/entry">redirect3 [A] entry</a></li>
        </ul>
      </div>
    </div>
  </div>

</body>

entry.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <h2>[B] entry</h2>
        <form action="/redirect/regist" method="POST" class="form-horizontal">
          <div class="form-group">
            <label for="name" class="col-sm-2 control-label">name</label>
            <div class="col-sm-10">
              <input class="form-control" id="name" name="name" type="text" />
            </div>
          </div>
          <div class="form-group">
            <label for="email" class="col-sm-2 control-label">email</label>
            <div class="col-sm-10">
              <input class="form-control" id="email" name="email" type="email" />
            </div>
          </div>
          <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
              <button type="submit" class="btn btn-default">送信</button>
            </div>
          </div>
        </form>
      </div>
      <div class="col-md-12 well">
        <div>
          <p>現在日時:<span th:text="${current}">current</span></p>
        </div>
        <div>
          <button class="back btn btn-default">戻る</button>
          <button class="forward btn btn-default">進む</button>
        </div>
      </div>
    </div>
  </div>

</body>

result.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <h2>[D] result</h2>
        <dl>
          <dt>id</dt>
          <dd th:text="${id}">id</dd>
          <dt>name</dt>
          <dd th:text="${name}">name</dd>
          <dt>email</dt>
          <dd th:text="${email}">email</dd>
        </dl>
        <div>
          <a href="/redirect/other">他のページ</a>
        </div>
      </div>
      <div class="col-md-12 well">
        <div>
          <p>flash scope message</p>
          <p th:text="${message}">message</p>
        </div>
        <div>
          <p>現在日時:<span th:text="${current}">current</span></p>
        </div>
        <div>
          <button class="back btn btn-default">戻る</button>
          <button class="forward btn btn-default">進む</button>
        </div>
      </div>
    </div>
  </div>

</body>

other.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <h2>[E] other</h2>
      </div>
      <div class="col-md-12 well">
        <div>
          <p>現在日時:<span th:text="${current}">current</span></p>
        </div>
        <div>
          <button class="back btn btn-default">戻る</button>
          <button class="forward btn btn-default">進む</button>
        </div>
      </div>
    </div>
  </div>

</body>

2. PRGパターンを使わない場合

下図の「RPGパターンを使わない」ときの画面遷移の挙動を確認します。

画面補足

  • [A] /index TOPページ
  • [B] /entry 登録フォームページ
  • [C] /regist 登録処理とその結果ページ
  • [E] /other 他のページ

確認のポイント

  1. [C] /registから戻るボタンを押したときの遷移先について
  2. [C] /registでページ再読み込みを行った後に戻るボタンを押したときの遷移先について
  3. [E] /otherから戻るボタンを押したときの遷移先について
PRGパターンを使わない場合の遷移図

  [A]                 [B]                    [C]                                            [E]
  /index              /entry                 /regist                                        /other
 +-----------+       +-------------+        +--------------+                               +-----------+
 | Index     |  GET  | Entry Form  |  POST  | Registration |                          GET  | Other     |
 | (Page)    |------>| (Page)      |------->|  & Result    |------------------------------>| (Page)    |
 |           |       |             |        | (Page)       |                               |           |
 +-----------+       +-------------+        +--------------+                               +-----------+
                          ^                       |     ^                                       |
                          |                       |     |                                       |
                          +----[Browser back]<----+     +------------[Browser back]<------------+


AddressバーのURL
  [A]-----------------[B]--------------------[C]---------------------------------------------[E]
  /index              /entry                 /regist                                         /other

スタックされたHistory
  [A]---------------->[B]------------------->[C]-------------------------------------------->[E]
                      /index                 /entry                                          /regist
                                             /index                                          /entry
                                                                                             /index

動作確認の結果

  • [C] /registへ遷移すると、historyに[B] /entryと、[A] /indexが記録されている。
  • [C] /registからブラウザの戻るボタンで戻ると[B] /entryへ遷移する。([B] /entryへのGETリクエストは発生しない)
  • [C] /registでページ再読み込みをしてもhistoryは変わらない。 ([C] /registへのPOSTリクエストが発生する)
  • [E] /otherからブラウザの戻るボタンで戻ると[C] /registへ遷移する。 ([C] /registへのPOSTリクエストは発生しない)

この画面遷移の問題点

  • [C] /registからブラウザの戻るボタンで[B] /entryへ戻り、再度フォームをサブミットすることができてしまう。
    • 対策として登録処理で2重登録のチェック処理の実装、登録時にワンタイムトークンを使用する。(PRGパターンの問題ではありません)
  • [C] /registでページ再読み込みを行うと登録処理が再び実行されてしまう。
    • 対策としてRPGパターンを適用する。

動作確認の結果 (Chromeのdevtoolsでキャッシュを無効化した状態)

赤字のところは上記のキャッシュが有効化されている場合との相違点です。

  • [C] /registへ遷移すると、historyに[B] /entryと、[A] /indexが記録されている。
  • [C] /registからブラウザの戻るボタンで戻ると[B] /entryへ遷移する。([B] /entryへのGETリクエストが発生する)
  • [C] /registでページ再読み込みをしてもhistoryは変わらない。 ([C] /registへのPOSTリクエストが発生する)
  • [E] /otherからブラウザの戻るボタンで戻ると[C] /registへ遷移する。 ([C] /registへのPOSTリクエストが発生する)

この画面遷移の問題点

  • [C] /registからブラウザの戻るボタンで[B] /entryへ戻り、再度フォームをサブミットすることができてしまう。
    • 対策として登録処理で2重登録のチェック処理の実装する。(PRGパターンの問題ではありません)
    • [B] /entryが再読み込みされるのでワンタイムトークンの実装は有効ではない。
  • [C] /registでページ再読み込みを行う、または[E] /otherからブラウザの戻るボタンで戻ってくると登録処理が再び実行されてしまう。
    • 対策としてRPGパターンを適用する。

検証用のコード

Form

PRGパターンを使う場合と同じ

Controller

Redirect2Controller
@Controller
@RequestMapping(value = "/redirect2")
public class Redirect2Controller {

  @RequestMapping(value = "/entry", method = RequestMethod.GET)
  public String entry(Model model) {
    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect2/entry";
  }

  @RequestMapping(value = "/regist", method = RequestMethod.POST)
  public String regist(RedirectForm form, Model model) {

    // ここはformの内容をDBに登録する処理
    // 登録IDを取得(みなし)
    String id = UUID.randomUUID().toString();
    model.addAttribute("id", id);
    // 登録結果をmodelにセット
    model.addAttribute("name", "rubytomato");
    model.addAttribute("email", "rubytomato@example.com");
    // 登録メッセージ
    model.addAttribute("message", "登録完了");

    Date current = new Date();
    model.addAttribute("current", current);

    return "redirect2/regist";
  }

  @RequestMapping(value = "/other", method = RequestMethod.GET)
  public String other(Model model) {
    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect2/other";
  }

}

Template

index.html

PRGパターンを使う場合と同じ

entry.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <h2>[B] entry</h2>
        <form action="/redirect2/regist" method="POST" class="form-horizontal">
          <div class="form-group">
            <label for="name" class="col-sm-2 control-label">name</label>
            <div class="col-sm-10">
              <input class="form-control" id="name" name="name" type="text" />
            </div>
          </div>
          <div class="form-group">
            <label for="email" class="col-sm-2 control-label">email</label>
            <div class="col-sm-10">
              <input class="form-control" id="email" name="email" type="email" />
            </div>
          </div>
          <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
              <button type="submit" class="btn btn-default">送信</button>
            </div>
          </div>
        </form>
      </div>
      <div class="col-md-12 well">
        <div>
          <p>現在日時:<span th:text="${current}">current</span></p>
        </div>
        <div>
          <button class="back btn btn-default">戻る</button>
          <button class="forward btn btn-default">進む</button>
        </div>
      </div>
    </div>
  </div>

</body>

regist.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <h2>[C] regist</h2>
        <dl>
          <dt>id</dt>
          <dd th:text="${id}">id</dd>
          <dt>name</dt>
          <dd th:text="${name}">name</dd>
          <dt>email</dt>
          <dd th:text="${email}">email</dd>
        </dl>
        <div>
          <a href="/redirect2/other">他のページ</a>
        </div>
      </div>
      <div class="col-md-12 well">
        <div>
          <p>message</p>
          <p th:text="${message}">message</p>
        </div>
        <div>
          <p>現在日時:<span th:text="${current}">current</span></p>
        </div>
        <div>
          <button class="back btn btn-default">戻る</button>
          <button class="forward btn btn-default">進む</button>
        </div>
      </div>
    </div>
  </div>

</body>

other.html

PRGパターンを使う場合と同じ

3. PRGパターンを使わない + History APIを使う場合

下図の「RPGパターンを使わない + History APIを使う」ときの画面遷移の挙動を確認します。
[C] /registへ遷移したときにHistory APIのreplaceStateを使って履歴を[C] /registから[D] /resultへ書き換えます。
これによってブラウザのアドレスバーは/resultとなります。
[D] /resultのページは、[C] /regist(アドレスバー上は/result)でページ再読み込みを行ったときや、[E] /otherから戻ってくるときのために用意します。

画面補足

  • [A] /index TOPページ
  • [B] /entry 登録フォームページ
  • [C] /regist 登録処理とその結果ページ
  • [D] /result 登録結果ページ
  • [E] /other 他のページ

[C] /regist[D] /resultは同じhtmlテンプレートを使います。

確認のポイント

  1. [C] /registから戻るボタンを押したときの遷移先について
  2. [C] /registでページ再読み込みを行った後に戻るボタンを押したときの遷移先について
  3. [E] /otherから戻るボタンを押したときの遷移先について
PRGパターンを使わない+HistoryAPIを使う場合の遷移図

  [A]                 [B]                    [C]                                            [E]
  /index              /entry                 /regist (->/result)                            /other
 +-----------+       +-------------+        +--------------+                               +-----------+
 | Index     |  GET  | Entry Form  |  POST  | Registration |                          GET  | Other     |
 | (Page)    |------>| (Page)      |------->|  & Result    |------------------------------>| (Page)    |
 |           |       |             |        | (Page)       |                          +--->|           |
 +-----------+       +-------------+        +--------------+                          |    +-----------+
                          ^                       |     |                             |             |
                          |                       |     |               [D]           |             |
                          |<---[Browser back]<----+     +-----[F5]----> /result       |             |
                          |                                            +-----------+  |             |
                          |                                            | Result    |--+             |
                          |                                            | (Page)    |                |
                          |                                            |           |                |
                          |                                            +-----------+                |
                          |                                               |    ^                    |
                          |                                               |    |                    |
                          +--------------------[Browser back]<------------+    +---[Browser back]<--+

AddressバーのURL
  [A]-----------------[B]--------------------[C]---------------------------------------------[E]
  /index              /entry                 /regist                                         /other
                                                ↓ (History APIで書き換え)
                                             /result

スタックされたHistory
  [A]---------------->[B]------------------->[C]-------------------------------------------->[E]
                      /index                 /entry                                          /result <---この履歴はHistory APIで書き換えたもの
                                             /index                                          /entry
                                                                                             /index
                                                                        [D]<-----------------[E]
                                                                        /entry
                                                                        /index

動作確認の結果

  • [C] /registへ遷移すると、historyに[B] /entryと、[A] /indexが記録されている。
  • [C] /regist(アドレスバー上は/result)からブラウザの戻るボタンで戻ると[B] /entryへ遷移する。([B] /entryへのGETリクエストは発生しない)
  • [C] /regist(アドレスバー上は/result)でページ再読み込みをしてもhistoryは変わらない。 ([D] /resultへのGETリクエストが発生する)
  • [C] /registを再読み込みした後の[D] /resultからブラウザの戻るボタンで戻ると[B] /entryへ遷移する。([B] /entryへのGETリクエストは発生しない)
  • [E] /otherからブラウザの戻るボタンで戻ると[D] /resultへ遷移する。 ([D] /resultへのGETリクエストは発生しない)

この画面遷移の問題点

  • [C] /registまたは[D] /resultからブラウザの戻るボタンで[B] /entryへ戻り、再度フォームをサブミットすることができてしまう。
    • 対策として登録処理で2重登録のチェック処理の実装、登録時にワンタイムトークンを使用する。(PRGパターンの問題ではありません)

動作確認の結果 (Chromeのdevtoolsでキャッシュを無効化した状態)

  • [C] /registへ遷移すると、historyに[B] /entryと、[A] /indexが記録されている。
  • [C] /regist(アドレスバー上は/result)からブラウザの戻るボタンで戻ると[B] /entryへ遷移する。([B] /entryへのGETリクエストが発生する)
  • [C] /regist(アドレスバー上は/result)でページ再読み込みをしてもhistoryは変わらない。 ([D] /resultへのGETリクエストが発生する)
  • [C] /registを再読み込みした後の[D] /resultからブラウザの戻るボタンで戻ると[B] /entryへ遷移する。([B] /entryへのGETリクエストが発生する)
  • [E] /otherからブラウザの戻るボタンで戻ると[D] /resultへ遷移する。 ([D] /resultへのGETリクエストが発生する)

この画面遷移の問題点

  • [D] /resultからブラウザの戻るボタンで[B] /entryへ戻り、再度フォームをサブミットすることができてしまう。
    • 対策として登録処理で2重登録のチェック処理の実装する。(PRGパターンの問題ではありません)
    • [B] /entryが再読み込みされるのでワンタイムトークンの実装は有効ではない。

検証用のコード

Form

PRGパターンを使う場合と同じ

Controller

Redirect3Controller
@Controller
@RequestMapping(value = "/redirect3")
public class Redirect3Controller {

  @RequestMapping(value = "/entry", method = RequestMethod.GET)
  public String entry(Model model) {
    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect3/entry";
  }

  @RequestMapping(value = "/regist", method = RequestMethod.POST)
  public String regist(RedirectForm form, Model model) {

    // ここにformの内容をDBに登録する処理
    // 登録IDを取得(みなし)
    String id = UUID.randomUUID().toString();
    model.addAttribute("id", id);
    // 登録結果をmodelにセット
    model.addAttribute("name", "rubytomato");
    model.addAttribute("email", "rubytomato@example.com");
    // 登録メッセージ
    model.addAttribute("message", "登録完了");

    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect3/regist";
  }

  @RequestMapping(value = "/result/{id}", method = RequestMethod.GET)
  public String result(@PathVariable("id") String id, Model model) {
    model.addAttribute("id", id);

    // ここにIDから登録情報を検索する処理
    // 検索結果をmodelにセット
    model.addAttribute("name", "rubytomato");
    model.addAttribute("email", "rubytomato@example.com");

    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect3/regist";
  }

  @RequestMapping(value = "/other", method = RequestMethod.GET)
  public String other(Model model) {
    Date current = new Date();
    model.addAttribute("current", current);
    return "redirect3/other";
  }

}

Template

index.html

PRGパターンを使う場合と同じ

entry.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <h2>[B] entry</h2>
        <form action="/redirect3/regist" method="POST" class="form-horizontal">
          <div class="form-group">
            <label for="name" class="col-sm-2 control-label">name</label>
            <div class="col-sm-10">
              <input class="form-control" id="name" name="name" type="text" />
            </div>
          </div>
          <div class="form-group">
            <label for="email" class="col-sm-2 control-label">email</label>
            <div class="col-sm-10">
              <input class="form-control" id="email" name="email" type="email" />
            </div>
          </div>
          <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
              <button type="submit" class="btn btn-default">送信</button>
            </div>
          </div>
        </form>
      </div>
      <div class="col-md-12 well">
        <div>
          <p>現在日時:<span th:text="${current}">current</span></p>
        </div>
        <div>
          <button class="back btn btn-default">戻る</button>
          <button class="forward btn btn-default">進む</button>
        </div>
      </div>
    </div>
  </div>

</body>

regist.html

<body>

  <div class="container-fluid">
    <div class="row">
      <div class="col-md-12 well">
        <h2>[C] regist</h2>
        <dl>
          <dt>id</dt>
          <dd th:text="${id}">id</dd>
          <dt>name</dt>
          <dd th:text="${name}">name</dd>
          <dt>email</dt>
          <dd th:text="${email}">email</dd>
        </dl>
        <div>
          <a href="/redirect3/other">他のページ</a>
        </div>
      </div>
      <div class="col-md-12 well">
        <div>
          <p>message</p>
          <p th:text="${message}">message</p>
        </div>
        <div>
          <p>現在日時:<span th:text="${current}">current</span></p>
        </div>
        <div>
          <button class="back btn btn-default">戻る</button>
          <button class="forward btn btn-default">進む</button>
        </div>
      </div>
    </div>
  </div>

<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
$(function(){
    if (window.location.pathname.indexOf("regist") != -1) {
        console.log("regist");
        var state = {a:1, b:2};
        window.history.replaceState(state, "result", /*[[ '/redirect3/result/' + ${id} ]]*/ "/redirect3/result/123456");
    }
});
/*]]>*/
</script>
</body>

other.html

PRGパターンを使う場合と同じ

History API

Methods

pushState

履歴をスタックするメソッド。

//履歴の追加
history.pushState(null, null, "/result");

replaceState

履歴の修正を行うメソッド。
通常はpushStateメソッドでスタックした履歴を修正するときに使用する。

//履歴の修正
history.replaceState(null, null, "/result");

Properties

length

スタックされているページ数を知る。

history.length;

state

現在の履歴エントリのstateを読み取る。

history.state;

イベント

popstate

pushStateメソッドでスタックした履歴へブラウザの戻る・進むボタンをクリックして移動したときに発生するイベント。
History APIを使わずに通常の画面遷移でスタックされた履歴ではイベントは発生しない。

$(window).on('popstate', function(event){
  //ブラウザの戻る・進むボタンがクリックされたときに行いたい処理を実装
});
20
15
1

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
20
15