ルート変更を監視するJavaScriptの詳細な説明

ルート変更を監視するJavaScriptの詳細な説明

フロントエンドでルーティング変更を実装する方法は主に2つあります。この2つの方法の最大の特徴は、リフレッシュ機能なしでURL切り替えを実装することです。

  1. ハッシュを変更して、window.onhashchange を使用してリッスンします。
  2. 履歴の変更により、ページをロードするための js 操作が実行されます。ただし、履歴はハッシュほど単純ではありません。ブラウザのいくつかの前後の操作 (history.back()、history.forward()、history.go() メソッドを使用して、ユーザーの履歴レコード内で前後にジャンプする) を除き、履歴の変更によって popstate イベントがアクティブにトリガーされるためです。PushState と replaceState は popstate イベントをトリガーしません。

歴史

主に歴史を理解するため

pushState() メソッド

これには、ステータス オブジェクト、タイトル (現在は無視されます)、(オプション) URL の 3 つのパラメータが必要です。それぞれについて詳しく説明しましょう。

状態オブジェクト — 状態オブジェクト状態は、pushState() を介して新しい履歴エントリを作成する JavaScript オブジェクトです。ユーザーが新しい状態に移動するたびに、popstate イベントが発生し、イベントの状態プロパティには履歴エントリの状態オブジェクトのコピーが含まれます。 状態オブジェクトは、シリアル化できるものであれば何でも構いません。その理由は、Firefox はユーザーがブラウザを再起動したときに使用するために状態オブジェクトをユーザーのディスクに保存し、状態オブジェクトのシリアル化された表現に 640k のサイズ制限を設定しているためです。シリアル化後に 640k を超える状態オブジェクトを pushState() メソッドに渡すと、メソッドは例外をスローします。より多くのスペースが必要な場合は、sessionStorage と localStorage を使用することをお勧めします。

title — Firefox は現在このパラメータを無視しますが、将来的には使用される可能性があります。ここで空の文字列を渡すと、このメソッドが将来変更されても安全になります。オプションで、リダイレクト先の状態の短いタイトルを渡すこともできます。

URL — このパラメータは、新しい履歴 URL レコードを定義します。ブラウザは pushState() を呼び出した直後に URL をロードするのではなく、ユーザーがブラウザを再度開いたときなど、後で URL をロードする場合があることに注意してください (リソースはロードされませんが、変更をリッスンしてビューを変更することができ、ページを更新せずに単一ページ ルーティングを実装する方法になります)。新しい URL は絶対パスである必要はありません。新しい URL が相対パスの場合、現在の URL を基準として扱われます。新しい URL は現在の URL と同じオリジン (同一オリジン ポリシー) である必要があります。そうでない場合、pushState() は例外をスローします。このパラメータはオプションであり、デフォルトでは現在の URL になります。

ある意味では、pushState() を呼び出すことは、現在のページに新しい履歴レコードを作成してアクティブ化する点で、window.location = "#foo" を設定することに似ています。しかし、pushState() には次のような利点があります。

新しい URL は、現在の URL と同じオリジンを持つ任意の URL にすることができます。逆に、ハッシュを変更する場合、window.location の設定は同じドキュメントのみになります。
URL を変更したくない場合は、変更しないでください。逆に、window.location = "#foo"; を設定すると、現在のハッシュが #foo でない場合にのみ新しい履歴項目が作成されます。
新しい履歴項目に任意のデータを関連付けることができます。ハッシュベースのアプローチでは、関連するすべてのデータを短い文字列にエンコードします。
その後、ヘッダーがブラウザによって使用される場合、このデータは使用できます (ハッシュは使用できません)。

新しい URL が古い URL とハッシュのみが異なる場合でも、pushState() は hashchange イベントをトリガーしないことに注意してください。

pushState() の使用シナリオ

履歴は更新せずにURLまたはURLパラメータを変更できます

window.history.replaceState('', '', `${window.location.origin}${window.location.pathname}type=a`);

replaceState() メソッド

history.replaceState() の使用は history.pushState() と非常に似ていますが、違いは replaceState() が新しい履歴項目を作成するのではなく、現在の履歴項目を変更することです。 ただし、これによって、グローバル ブラウザ履歴に新しい履歴項目が作成されなくなるわけではないことに注意してください。
作る

ポップステートイベント

window.onpopstate を使用して戻りイベントをリッスンする

window.onpopstate = funcRef;

funcRef : (イベント:{状態:任意})=>void

アクティブな履歴レコードが変更されるたびに、対応するウィンドウ オブジェクト (window.onpopstate) で popstate イベントがトリガーされます。現在アクティブな履歴エントリが history.pushState() メソッドによって作成されたか、または history.replaceState() メソッドによって変更された場合、popstate イベント オブジェクトの状態プロパティには、履歴エントリの状態オブジェクトのコピーが含まれます。

**知らせ:

  1. history.pushState() または history.replaceState() を呼び出しても、popstate イベントはトリガーされません。popstate イベントは、戻るボタンまたは進むボタンのクリック (または JavaScript で history.back()、history.forward()、history.go() メソッドの呼び出し) などの特定のブラウザー アクションによってのみトリガーされます。さらに、a タグのアンカーによってもイベントがトリガーされます。
  2. Web ページが読み込まれると、popstate イベントがトリガーされるかどうかについては、ブラウザごとに動作が異なります。Chrome と Safari は popstate イベントをトリガーしますが、Firefox はトリガーしません。

pushState と replaceState を監視する方法は?

サブスクリプション公開モードを通じて、これを自分で実装することができます。まず、サブスクリプション公開モードであるDepとWatchを使用します。これは、実際にはVueソースコードdepとwantcher間の実装方法の簡略化されたバージョンです。

class Dep { // サブスクリプションプールコンストラクター(名前){
        this.id = new Date() //ここでは、サブスクリプションプールのIDとしてタイムスタンプを使用します
        this.subs = [] //このイベントでサブスクライブされたオブジェクトのコレクション}
    defined(){ // サブスクライバーを追加します Dep.watch.add(this);
    }
    notification() { // 購読者に変更を通知する this.subs.forEach((e, i) => {
            if(typeof e.update === 'function'){
                試す {
                   e.update.apply(e) // サブスクライバー更新関数をトリガーする} catch(err){
                    コンソール.warr(エラー)
                }
            }
        })
    }
    
}
Dep.watch = null;

クラスウォッチ{
    コンストラクタ(名前,関数){
        this.name = name; //サブスクリプションメッセージの名前 this.id = new Date(); //ここでは、タイムスタンプをサブスクライバーのIDとして使用します
        this.callBack = fn; //サブスクリプションメッセージが送信され変更されると、サブスクライバーによってコールバック関数が実行されます}
    add(dep) { // サブスクライバーを dep サブスクリプション プールに追加します dep.subs.push(this);
    }
    update() { // サブスクライバーメソッドを更新 var cb = this.callBack; // 関数内で呼び出される this を変更しないように割り当てる
        cb(この名前);          
    }
}

historyメソッドを再実装し、addHistoryListenerメソッドを追加します。

const addHistoryMethod = (関数(){
 var historyDe​​p = new Dep() // サブスクリプションプールを作成する return function (name) {
  if(name==='履歴変更'){
   var event = new Watch(name,fn);
   依存関係ウォッチ = evnet;
   historyDe​​p.defind(); // サブスクライバーを追加 Dep.watch = null;
  }それ以外の場合(name==='pushState'||name==='replaceState'){
   var メソッド = history[名前];
   関数()を返す{
    method.apply(履歴、引数)
    履歴を通知します。
   }
  }
 }
})()
window.addHistoryListener = addHistoryMethod('historyChange')
history.pushState = addHistoryMethod('pushState');
history.replaceState = addHistoryMethod('replaceState');

カプセル化は成功しました。テスト使用例

window.addHistoryListener('履歴',function(){
 console.log('ウィンドウ履歴が変更されました')
})
window.addHistoryListener('履歴',function(){
 console.log('ウィンドウ履歴が変更されました。私もそれを聞きました') // 複数のリスニングイベントをバインドできます console.log(history.state)
})
history.pushState({foo:bar}, 'title', '/car')

現在のステータスを取得する

ページが読み込まれると、null 以外の状態オブジェクトが存在する場合があります。これは、たとえば、ページが状態オブジェクトを(pushState() または replaceState() メソッドを介して)設定し、その後ユーザーがブラウザを再起動した場合などに発生する可能性があります。その後、ページがリロードされると、ページは onload イベントを受信しますが、popstate イベントは受信しません。ただし、history.state プロパティを読み取ると、popstate がトリガーされた場合と同じ状態オブジェクトが取得されます。

popstate イベントを待たずに現在の履歴項目の状態オブジェクトを読み取ることができます。次のように history.state プロパティを使用します。

現在の状態を history.state とします。

対比

プッシュステート状態を置き換える
現在のページで新しい履歴レコードが作成され、アクティブ化されます。戻るボタンをクリックすると、前の URL に戻ります。現在の履歴が変更されます。戻るボタンを押すと、変更された URL はスキップされます。

要約する

履歴は非更新ルーティングを実装する方法であり、安定したシステムエクスペリエンスを確保するための単一ページ開発に特に適しています。ただし、履歴は pushState と replaceState の動作を監視せず、go、back、forward の動作のみを監視します。ただし、サブスクリプション公開モードを使用し、Dep と Watch を使用し、pushState および replaceState イベントを再パッケージ化し、呼び出し後に通知メソッドを自動的にトリガーし、addHistoryListener メソッドを追加してリスニング コールバック (サブスクライバー) を追加することができます。

これで、JavaScript を使用してルート変更を監視する方法についての記事は終了です。JavaScript を使用してルート変更を監視する方法の詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • vue.js でルートの変更を監視するために watch を使用する方法
  • AngularJS でルートの変更を監視する方法
  • AngularJS はルート変更をリッスンします サンプルコード

<<:  Dockerでプロジェクトを実行する方法

>>:  MySQL テーブル削除操作の実装 (delete、truncate、drop の違い)

推薦する

初心者向けWebサイト構築ガイド⑥:FlashFXPの詳しい使い方

今日は、サイトの設定やウェブサイトのアップロードなど、FlashFXP の最も基本的な機能を紹介しま...

Tomcat で複数の war パッケージを展開する方法と手順

1 背景JDK1.8-u181とTomcat8.5.53がインストールされました。インストール後、環...

Alibaba Cloud Centos 7.5 に MySQL をインストールするチュートリアル

CentOS 7 の yum ソースには、MySQL を正常にインストールするための mysql-s...

Power Shell に vim 実装コード例を追加する方法

1. Vimの公式ウェブサイトにアクセスして、オペレーティングシステムに適した実行ファイルをダウンロ...

CSS で画像アダプティブ コンテナを実装するためのサンプル コード

多くの場合、画像をコンテナのサイズに合わせて調整する必要があります。 1. imgタグ方式幅と高さを...

docker-compose を使用して Clickhouse をすばやくデプロイする方法のチュートリアル

ClickHouse は、オープンソースの列指向 DBMS (Yandex によって開発) です。 ...

画像比較を実現するjQueryプラグイン

この記事の例では、画像比較を実現するためのjQueryプラグインの具体的なコードを参考までに共有して...

Hタグの定義と注意事項について簡単に説明します

結果から判断すると、タイトルを定義するための固定パターンはなく、すべてむしろランダムな感じがします。...

ffmpeg コマンドラインを使用してビデオを変換するためのサンプルコード

この記事の本文を始める前に、まず ffmpeg プログラムをインストールする必要があります (Lin...

WeChatアプレットがフォーム検証を実装

WeChatアプレットフォームの検証、参考までに具体的な内容は次のとおりです。プラグインWxVali...

便利で使いやすいウェブアプリケーションを設計するための 10 のヒント

より使いやすい Web アプリケーションを設計するための 10 のヒントをご紹介します。ヒント1: ...

MySQL インデックスの種類 (通常、ユニーク、フルテキスト) の説明

MySQL のインデックスの種類には、通常のインデックス、一意のインデックス、全文インデックスがあり...

Mysqlデータベースの文字化けに対処する方法

MySQL では、データベースの文字化けは一般的に文字セットを設定することで修正できますが、文字化け...

MySQL 8.0.13 で日付を 0000-00-00 00:00:00 に設定すると発生する問題を解決する

データベース操作を学び始めたばかりです。今日、データを保存していたところ、エラーが発生していることに...

docker run 起動パラメータ コマンドを表示する方法 (推奨)

runlike を使用してコンテナの docker run 起動パラメータを表示します。 pipを...