独自のネイティブ JavaScript ルーターを作成する方法

独自のネイティブ JavaScript ルーターを作成する方法

序文

ルーティングを考えるとき、通常は React のようなライブラリを思い浮かべます。しかし実際には、これらのライブラリとフレームワークは依然としてバニラ JavaScript を使用しています。では、どうすればこれを達成できるのでしょうか?

この「JavaScript ルーティング チュートリアル」が、ネイティブ js で独自のルーターを作成する方法を理解するのに役立つことを願っています。

導入

さまざまな理由で独自のルーティングを作成したいという人によく出会います。この記事を読んでいるということは、あなたもその一人かもしれません!

最も重要なのは、vanillajsrouter を使用するとフレームワークへの依存が減ることです。

実装に関係するすべての部分を理解していれば、Vanilla JavaScript で独自のルーティングを作成するのは比較的簡単です。

独自の JS ルーターを作成するときに知っておくべき重要な点は次のとおりです。

1. ネイティブ JS ルーティングの鍵となるのは location.pathname プロパティです。

2. .pathname の変更に応じて「popstate」イベントをリッスンします。これは、ブラウザのアドレス バーに新しい URL が入力されるたびに発生しますが、ページを更新するのではなく、新しいコンテンツを読み込んでビューを更新するだけです。

3. ルートをroutes[]配列に保存することを選択できます。

4. URL を解析するには、JavaScript 正規表現 ( RegEx ) を使用する必要があります。

5. ルーティングをネイティブ ブラウザ アーキテクチャに統合する場合は、履歴と history.pushState (JavaScript の History API) の基本的な理解が不可欠です。

まず、History API を扱います。

JavaScript 履歴 API

JavaScript History API について言及していない、標準的な JS ルーターのチュートリアルをたくさん見てきました。それは残念なことです。ブラウザの「戻る」ボタンと「進む」ボタンをクリックすると、閲覧履歴内の URL に移動することになるからです。 History API がなければ、ルーティングについて話す方法はありません。

1.history.back() は history.go(-1) と同じで、ユーザーがブラウザの [戻る] ボタンをクリックしたときと同じです。どちらの方法でも同じ効果が得られます。

2. ユーザーがブラウザの「進む」ボタンを押すと、history.forward() が実行されます。これは history.go(1) と同じです。

3.go() は .back() メソッドや forward() メソッドと似ていますが、ブラウザの履歴スタック内で前進または後退するステップ数を指定できる点が異なります。 。

4. pushState() は新しい状態を History API にプッシュします。

5..length プロパティは、セッション履歴内の要素の数です。

6..state プロパティは、「popstate」イベントをリッスンせずに状態を見つけるために使用されます。

独自のネイティブJSルーティングを実装する

History API に基づく Vanilla JS ルーティング設定

まず、URL スイッチャー (ページを更新せずに) を構築するために必要な最小限のコードを詳しく見て、次にそれがどのように動作するかを示す GIF を紹介します。

<html>
    <ヘッド>
        <title>こんにちは</title>
        <スクリプトタイプ = "モジュール">
            関数 select_tab(id) {
                // すべてのボタンから選択したクラスを削除します
                document.querySelectorAll(".route").forEach(item => item.classList.remove('selected'));
                // クリックした要素を選択する(視覚的に)
                document.querySelectorAll("#" + id).forEach(item => item.classList.add('selected'));
            }
            関数load_content(id) {
                // テキストを更新します「{id} のコンテンツを読み込んでいます...」
                // もちろん、ここでコンテンツの読み込みマジックを実行します
                // リソースを更新するために Fetch API を実行する必要があるかもしれません
                document.querySelector("#content").innerHTML = '/' + id + '...' のコンテンツを読み込んでいます。
            }
            関数push(イベント) {
                // クリックされたボックス、ボタン、またはリンクの id 属性を取得します
                id = event.target.id とします。
                // クリックしたボタン/タブ/ボックスを視覚的に選択する
                select_tab(id);
                // ウィンドウのタブのタイトルを更新
                ドキュメントのタイトル = id;
                // このタブ/ページのコンテンツを読み込む
                コンテンツをロードします。
                // 最後に状態の変更をアドレスバーにプッシュします
                window.history.pushState({id}, `${id}`, `/page/${id}`);
            }
            window.onload = イベント => {
                // ボックスがクリックされたときに履歴push()イベントを追加します
                window["home"].addEventListener("click", イベント => push(イベント))
                window["about"].addEventListener("click", イベント => push(イベント))
                window["ギャラリー"].addEventListener("クリック", イベント => push(イベント))
                window["contact"].addEventListener("click", イベント => push(イベント))
                window["help"].addEventListener("click", イベント => push(イベント))
            }
            // PopStateEvent をリッスンします (戻るまたは進むボタンがクリックされます)
            window.addEventListener("popstate", イベント => {
                // 履歴状態IDを取得する
                stateId = event.state.id; とします。
                // クリックされた ID をコンソールに表示する (単なる楽しみのため)
                コンソールにログ出力します。
                // クリックしたボタン/タブ/ボックスを視覚的に選択する
                select_tab(状態ID);
                // このタブ/ページのコンテンツを読み込む
                コンテンツをロードします。
            });
        </スクリプト>
        <スタイル>
            * { /* グローバルフォント */
                フォントファミリー: Verdana;
                フォントサイズ: 18px;
            }
            #root { display: flex; flex-direction: row; }
            #content { display: flex;
                表示: ブロック;
                幅: 800ピクセル;
                高さ: 250px;
                /* 垂直中央揃えのテキスト */
                行の高さ: 250px;
                境界線: 2px 実線 #555;
                マージン: 32px;
                テキスト配置: 中央;
            }
            .ルート{
                カーソル: ポインタ;
                コンテンツの中央揃え: 中央;
                幅: 150ピクセル;
                高さ: 50px;
                /* 垂直中央揃えのテキスト */
                行の高さ: 50px;
                位置: 相対的;
                境界線: 2px 実線 #555;
                背景: 白;
                テキスト配置: 中央;
                マージン: 16px;
            }
            .route.selected { 背景: 黄色; }
        </スタイル>
    </head>

    <本文>

        <セクション id = "ルート">
            <section class = "route" id = "home">/home</section>
            <section class = "route" id = "about">/about</section>
            <section class = "route" id = "gallery">/ギャラリー</section>
            <section class = "route" id = "contact">/contact</section>
            <section class = "route" id = "help">/help</section>
        </セクション>

        <main id = "content">コンテンツを読み込んでいます...</main>
    
    </本文>

</html>

コアとなるのは、window.history.pushState({id}, ${id}, /page/${id}); を呼び出すことです。

最初のパラメータは状態の一意の ID、2 番目は「タブ タイトル」のテキスト、3 番目のパラメータはアドレス バーに表示するパスです。これにより、ブラウザはページを再読み込みせずに URL を変更できるようになります。

結果。これで、ボタンをクリックするたびに、ブラウザのアドレスバーの URL が実際に変更されます。コンテンツボックスも更新されます。

ネイティブ JS ルーターが動作可能になりました。ボタンがクリックされるたびに history.pushState がトリガーされることに注意してください。要素の id 属性に保存されているクリックされた要素の id (home、about、gallery など) を渡すだけです。これらは、移動先の実際のページに対応している必要があります。もちろん、これがページ名を保存する唯一の方法ではありません。array[] やその他の方法を使用することもできます。この例ではこのように実行されます。

もちろん、その場所のレイアウトとリソースもサーバーから読み込む必要があります。それはあなたのプログラムによって異なります。それは何でもあり得ます。

「戻る」ボタンと「進む」ボタンを機能させる

history.pushState を使用すると、「戻る」ボタンと「進む」ボタンが自動的に前の状態または次の状態に移動します。これを行うと、popstate イベントが生成されます。これは、ビューを再度更新する必要がある部分です。 (最初はボタンをクリックしたときです。)

ただし、イベントにはクリックの ID が含まれるため、「戻る」または「進む」がクリックされたときにビューを更新してコンテンツを再読み込みするのは簡単です。

ここでは react や vue を使用していないため、ソース コードでは load_content が DOM 内で直接ビューを更新する役割を担います。この領域には、API によって読み込まれたコンテンツが表示される場合があります。これは単なる「フロントエンド」の例なので、あまり詳しくはお見せできません。しかし、クライアント側ではそのように動作します。

サーバー側ルーティング負荷を初期化する

すべてをまとめるには、もう 1 つの手順が必要です。私の例では、router.html のみが使用されました。このルートを PWA に初めて読み込むときは、アドレス バーに /page/home を直接入力した場合に機能することを確認する必要があります。

これまでのところ、フロントエンドからのルーターのアドレスのみを変更しました。ルーターのボタンに表示される URL に移動するたびに、その URL が実際にはサーバーから個別に読み込まれると想定します。

したがって、/page/about ルーターとページがアプリケーションのルート ビューに読み込まれるようにするのはユーザーの責任です。 「現在」ボタンも強調表示されます。

実装すると、ルーティングが完了します。 #content 要素内のコンテンツをどのようにリロードするかは、完全にユーザーとバックエンドの設計次第です。

上記は、独自のネイティブ JavaScript ルーターを作成する方法の詳細です。ネイティブ JavaScript ルーターの作成の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • メンテナンス可能なオブジェクト指向 JavaScript コードの作成
  • JavaScript を使用してメンテナンス可能なスライドショー コードを作成する
  • JavaScriptのURLオブジェクトとは何かについて話しましょう
  • JavaScript における正規表現の実際的な応用の詳細な説明
  • JavaScript で配列遅延評価ライブラリを実装する方法
  • Javascript実践におけるコマンドモードの詳しい説明
  • JavaScript でアルゴリズムの複雑さを学ぶ方法
  • いくつかの面接の質問を使ってJavaScriptの実行メカニズムを調べる
  • メンテナンス可能なJSコードの書き方を教えます

<<:  Windows 64 ビット版 MySQL 5.7 以降の解凍パッケージにデータディレクトリと my-default.ini がなく、サービスが起動できない問題の簡単な解決方法 (問題概要)

>>:  LinuxサーバにおけるNginxとApacheの共存の実装方法の分析

推薦する

ウェブページ上の小さなスペースに大きな画像を配置する方法

出典: www.bamagazine.comウェブページのバナー、ニュースの見出しの周りのスペース、...

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

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

CSS3で実装された天気アイコンのアニメーション効果

成果を達成する 実装コードhtml <div class="wrapper"...

JavaScript はパスワードボックスの入力検証を実装します

サーバーの負荷を軽減するために、ユーザーが入力するときにフロントエンドページで簡単な検証を実行する必...

MySQL ジョイントインデックス(複合インデックス)の実装

共同インデックスこの記事におけるジョイントインデックスの定義は次のとおりです (MySQL): AL...

Dockerイメージサイズを最適化する一般的な方法

通常、私たちが構築する Docker イメージはサイズが大きく、多くのディスク領域を占有します。コン...

Vue の foreach 配列と js の traversal 配列の書き方の説明

Vue foreach配列を記述し、jsで配列をトラバースする方法シナリオVueでAxiosを使用し...

HTML にネストされた div の無効なマージンに対する解決策

div がネストされているときに margin が機能しない問題の解決策を次に示します。さて、マージ...

Linux ソースコードからのソケット (TCP) バインドの詳細な説明

目次1. 最も単純なサーバー側の例2. バインドシステムコール2.1、inet_bind 2.2、i...

Vue2.0+ElementUI+PageHelperで実装されたテーブルページング機能

序文最近、いくつかのフロントエンド プロジェクトに取り組んでおり、ページにいくつかのテーブルを表示す...

単一の MySQL テーブルで数千万のデータを処理するアイデアを共有する

目次プロジェクトの背景改善案データ特性を観察するマルチプロセスアイデアの要約データ処理スキルプロジェ...

MySQL マスタースレーブレプリケーションの原理と実践の詳細な説明

目次導入効果原理形状練習するこの記事では、例を使用して、MySQL マスター/スレーブ レプリケーシ...

Linux で mysql-8.0.20 をインストールするための詳細なチュートリアル

** Linuxにmysql-8.0.20をインストールする**環境の紹介オペレーティングシステム:...

MySQL 文字セットの文字化けとその解決方法

序文文字セットは、一連のシンボルとエンコード規則です。Oracle データベースでも MySQL デ...

du コマンドを使用して Linux システム ディレクトリのサイズを取得する方法

Linux システムを使用したことがある人なら、Linux システムの ls コマンドは通常、ファイ...