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

推薦する

HTML検証 HTML検証

HTML 検証はHTML 検証を指します。これは、HTML ドキュメントを分析し、標準の HTML ...

Node.js のモジュール性、npm パッケージ マネージャーの説明

目次モジュール化の基本概念モジュール化とは何かモジュール分解の利点Node.js のモジュール性No...

Vue プロジェクトで Baidu Map API を使用する方法

目次1. Baidu Map Open Platformにアカウントを登録してログインする2. 必要...

Vueのsync修飾子の詳細な説明

目次1. 手順2. 修飾語3. .sync 修飾子4. まとめ1. 手順指示とは命令です。文字通りの...

HTML で div を非表示にする テーブルを非表示にする TABLE または DIV コンテンツの CSS スタイル

今夜、数日間悩まされていた問題を解決しました。本当に解決したかどうかはわかりませんが、解決されている...

vue.config.js からプロジェクト最適化までの vue2.x 構成

目次序文vue.config.js 構成オプションパッケージサイズを縮小するためのパッケージの最適化...

Dockerは同じIPネットワークセグメントとの接続を実現する

最近、Docker とホストが同じネットワーク セグメント上で通信する問題を解決し、そのプロセス全体...

Vue でのルータービューコンポーネントの使用に関する詳細な説明

Vue プロジェクトを開発する場合、さまざまなコンポーネント ページを表示するために切り替えることが...

MacOS で Docker を使用して MySQL マスター スレーブ データベースを作成する方法

1. MySQLイメージを取得するターミナルから最新のMySQLイメージを取得するdocker pu...

dockerでopenGaussデータベースを構成する方法の詳細な説明

Windowsユーザー向けDocker で openGauss を使用するopenGaussイメージ...

Kubernetes の応用分野の概要

Kubernetes は、アプリケーションの移植性とハイブリッド クラウド/マルチクラウドの展開をサ...

JSON.stringify の簡易版の実装とその 6 つの主要機能の詳細な説明

目次序文JSON.stringify の 6 つの機能特集1特集2特集3特集4特集5特集6手動で文字...

CSS3 すりガラス効果

すりガラス効果がうまく表現されていれば、ページが非常に鮮やかで立体的に見えるようになります。写真に直...

Mapper SQL ステートメント フィールドとエンティティ クラス属性名の関係は何ですか?

背景: 1. データベースに通知テーブルがある あなたは見ることができますgmt_create、通知...