独自のネイティブ 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の共存の実装方法の分析

推薦する

Linux カーネル デバイス ドライバー カーネル時間管理に関する注意事項

/****************** * Linux カーネルの時間管理 ***********...

Dockerがコンテナを作成した後にホスト名を変更する詳細なプロセス

後悔を癒す薬は世の中にある、考えてみる気さえあれば!コンテナを再作成する必要はもうありません。 m2...

Windows システムに VirtualBox と Ubuntu 16.04 をインストールするための詳細なチュートリアル

1. ソフトウェアの紹介バーチャルボックスVirtualBox は、無料のオープンソース仮想マシン ...

Nginxの現在の制限設定の詳細な説明

この記事では、最も単純なものから最も複雑なものまで、Nginx の現在の制限構成を例を使って説明しま...

Linux システムを起動時に自動的にスクリプトを実行するように設定する方法の例

序文みなさんこんにちは。私は梁旭です。職場では、システムの起動後にスクリプトやサービスを自動的に開始...

CSS ラベルモード表示プロパティの詳細な説明

コードは次のようになります。 <!DOCTYPE html> <html> ...

JavaScript の重要なブレークポイント デバッグ手法の概要 (推奨)

目次デバッガーを使用する理由は何ですか? Chromeデバッガーの基本的な使い方VS Code によ...

MySQL 8.0.11 Community Green Edition の Windows 用インストール手順図

このチュートリアルでは、インストールに最新の MySQL コミュニティ グリーン バージョンである ...

Mysqlの日付と時刻関数を扱う記事

目次序文1. 現在の時刻を取得する1.1 現在の日付と時刻を返す1.2 現在の日付を取得する1.3 ...

ドラッグアンドドロップでVueユーザーインターフェースを生成する方法

目次序文1. 技術原理1.1 レイアウト1.2 コンポーネント1.3 ステータス1.4 イベント1....

CSS疑似クラス名を数字で始めないでください

初心者が div+css を開発する場合、.ggg、#ccc などの形式の CSS 疑似クラス名を付...

画像マーキー効果を実現するネイティブJS

今日は、ネイティブ JS で実装された画像マーキー効果を紹介します。効果は次のとおりです。 実装され...

Nginx の add_header ディレクティブに注意する必要があるのはなぜですか?

序文ご存知のとおり、nginx 構成ファイルは add_header ディレクティブを使用して応答ヘ...

Vue グローバル フィルターの概念、注意事項、基本的な使用方法

目次1. フィルターの概念1. グローバルフィルターのフォーマットをカスタマイズする2. フィルター...

純粋な CSS3 でモバイルの拡大と縮小の効果を実装するためのサンプル コード

この記事では、純粋な CSS3 を使用してモバイル端末での展開と折りたたみの効果を実装するサンプルコ...