ブラウザの自動更新を実装するReactサンプルコード

ブラウザの自動更新を実装するReactサンプルコード

シングルページ アプリケーションが今日非常に人気となっているため、かつては驚異的だったフロントエンド ルーティングが、主要なフレームワークの基本標準となっています。各フレームワークは強力なルーティング機能を提供するため、ルーティングの実装は複雑になります。ルーティングの内部実装を理解するのはまだ少し難しいですが、ルーティング実装の基本原則を理解するだけであれば比較的簡単です。本記事では、フロントエンドルーティング、ハッシュ、ヒストリーの主流の実装方法を対象に、ネイティブ JS/React/Vue の 6 つのバージョンを参考として提供します。各バージョンの実装コードは 25 行から 40 行程度です (空白行を含む)。

フロントエンドルーティングとは何ですか?

ルーティングの概念はサーバーから来ており、ルーティングは URL と処理機能間のマッピング関係を記述します。

Web フロントエンドのシングルページ アプリケーション SPA (シングル ページ アプリケーション) では、ルーティングは URL と UI 間のマッピング関係を表します。このマッピングは一方向です。つまり、URL を変更すると UI が更新されます (ページは更新されません)。

フロントエンドルーティングを実装するにはどうすればいいですか?

フロントエンド ルーティングを実装するには、次の 2 つの主要な問題に対処する必要があります。

ページを更新せずに URL を変更するにはどうすればよいですか? URL が変更されたことを検出するにはどうすればよいでしょうか?

次の 2 つの主要な質問には、それぞれハッシュと履歴の実装を使用して回答します。

ハッシュ実装

  • ハッシュは、ハッシュ ( # ) で始まりハッシュで終わる URL の部分です。ページ内を移動するためのアンカーとしてよく使用されます。URL のハッシュ部分を変更しても、ページは更新されません。
  • hashchange イベントを通じて URL の変更を監視します。URL を変更する方法はいくつかあります。ブラウザを前後に動かして URL を変更する、標簽改變URL、通過wind 、です。これらの変更により、hashchange イベントがトリガーされます。

歴史の実装

  • History には、pushState と replaceState という 2 つのメソッドがあります。これら 2 つのメソッドは、ページを更新せずに URL のパス部分を変更します。
  • history は hashchange イベントに似た popstate イベントを提供しますが、popstate イベントは多少異なります。popstate イベントは、ブラウザを前後に移動して URL が変更されたときにトリガーされ、 pushState/replaceStateまたは tags によって URL が変更されたときには popstate イベントはトリガーされません件。好在我們可以攔截pushState/r 、クリック イベントにラベルを付けて URL の変更を検出できるため、URL の変更を監視することは可能ですが、hashchange ほど便利ではありません。

フロントエンドルーティング実装のネイティブJSバージョン

前のセクションで説明した 2 つの実装方法に基づいて、ハッシュ バージョンと履歴バージョンのルーティングがそれぞれ実装されます。この例では、ネイティブ HTML/JS 実装を使用し、フレームワークに依存しません。

ハッシュベースの実装

操作効果:

cbbb0cd6008139afcd5158c5feadfdb5.png

HTML部分:

<本文>
  <ul>
ref=""> <!-- ルートを定義する -->
    <li><a href="#/home" rel="external nofollow" >ホーム</a></li>
    <li><a href="#/about" rel="external nofollow" >について</a></li>
 
ref=""> <!-- ルートに対応する UI をレンダリングします -->
    <div id="ルートビュー"></div>
  </ul>
</本文>

JavaScript部分:

// ページはロード後にハッシュ変更をトリガーしません。ここでは、ハッシュ変更イベントをアクティブにトリガーします。window.addEventListener('DOMContentLoaded', onLoad)
// ルートの変更をリッスンする window.addEventListener('hashchange', onHashChange)
 
// ルーティングビュー var routerView = null
 
関数onLoad(){
  ルータービュー = document.querySelector('#routeView')
  ハッシュ変更()
}
 
// ルートが変更されたら、ルートに応じて対応するUIをレンダリングします
関数onHashChange() {
  スイッチ (location.hash) {
    ケース '#/home':
      routerView.innerHTML = 'ホーム'
      戻る
    ケース '#/about':
      routerView.innerHTML = '概要'
      戻る
    デフォルト:
      戻る
  }
}

履歴ベースの実装

操作効果:

d1469967dcc98af85ee83cc40b039980.png

HTML部分:

<本文>
  <ul>
    <li><a href='/home'>ホーム</a></li>
    <li><a href='/about'>について</a></li>
 
    <div id="ルートビュー"></div>
  </ul>
</本文>

JavaScript部分:

// ページはロード後にハッシュ変更をトリガーしません。ここでは、ハッシュ変更イベントをアクティブにトリガーします。window.addEventListener('DOMContentLoaded', onLoad)
// ルートの変更をリッスンする window.addEventListener('popstate', onPopState)
 
// ルーティングビュー var routerView = null
 
関数onLoad(){
  ルータービュー = document.querySelector('#routeView')
  オンポップステート()
 
 href=""> //<a> タグのクリック イベントのデフォルトの動作をインターセプトします。クリックされると、pushState を使用して URL を変更し、手動 UI を更新することで、リンクをクリックしたときに URL と UI を更新する効果を実現します。
  var linkList = document.querySelectorAll('a[href]')
  linkList.forEach(el => el.addEventListener('click', 関数(e) {
    e.preventDefault()
    history.pushState(null, '', el.getAttribute('href'))
    オンポップステート()
  }))
}
 
// ルートが変更されたら、ルートに応じて対応するUIをレンダリングします
関数onPopState(){
  スイッチ (場所.パス名) {
    '/home'の場合:
      routerView.innerHTML = 'ホーム'
      戻る
    ケース '/about':
      routerView.innerHTML = '概要'
      戻る
    デフォルト:
      戻る
  }
}

フロントエンドルーティング実装のReactバージョン

ハッシュベースの実装

操作効果:

ceb8b03a3af741f98955d1fc1d5ea506.png

使用方法は react-router と似ています。

  <ブラウザルーター>
    <ul>
      <li>
        <Link to="/home">ホーム</Link>
      </li>
      <li>
        <Link to="/about">について</Link>
      </li>
    </ul>
 
    <Route path="/home" render={() => <h2>ホーム</h2>} />
    <Route path="/about" render={() => <h2>概要</h2>} />
  </ブラウザルーター>

ブラウザルータの実装

デフォルトのクラス BrowserRouter をエクスポートし、React.Component を拡張します {
  状態 = {
    現在のパス: utils.extractHashPath(window.location.href)
  };
 
  onHashChange = e => {
    const currentPath = utils.extractHashPath(e.newURL);
    console.log("onHashChange:", 現在のパス);
    this.setState({ currentPath });
  };
 
  コンポーネントマウント() {
    window.addEventListener("ハッシュ変更"、this.onHashChange);
  }
 
  コンポーネントのマウントを解除します(){
    window.removeEventListener("ハッシュ変更"、this.onHashChange);
  }
 
  与える() {
    戻る (
      <RouteContext.Provider 値 = {{currentPath: this.state.currentPath}}>
        {this.props.children}
      </ルートコンテキスト.プロバイダー>
    );
  }
}

ルートの実装

エクスポートデフォルト({パス、レンダリング})=>(
  <ルートコンテキスト.コンシューマー>
    {({currentPath}) => currentPath === パス && render()}
  </RouteContext.Consumer>
);

リンクの実装

export default ({ to, ...props }) => <a {...props} href={"#" + to} />;

履歴ベースの実装

操作効果:

537e863d46a6ae5d5380e909fd086752.png

使用方法は react-router と似ています。

  <履歴ルーター>
    <ul>
      <li>
        <Link to="/home">ホーム</Link>
      </li>
      <li>
        <Link to="/about">について</Link>
      </li>
    </ul>
 
    <Route path="/home" render={() => <h2>ホーム</h2>} />
    <Route path="/about" render={() => <h2>概要</h2>} />
  </履歴ルーター>

HistoryRouter 実装

デフォルトのクラス HistoryRouter をエクスポートし、React.Component を拡張します {
  状態 = {
    現在のパス: utils.extractUrlPath(window.location.href)
  };
 
  onPopState = e => {
    定数 currentPath = utils.extractUrlPath(window.location.href);
    console.log("onPopState:", 現在のパス);
    this.setState({ currentPath });
  };
 
  コンポーネントマウント() {
    window.addEventListener("popstate", this.onPopState);
  }
 
  コンポーネントのマウントを解除します(){
    window.removeEventListener("popstate", this.onPopState);
  }
 
  与える() {
    戻る (
      <RouteContext.Provider 値 = {{currentPath: this.state.currentPath, onPopState: this.onPopState}}>
        {this.props.children}
      </ルートコンテキスト.プロバイダー>
    );
  }
}

ルートの実装

エクスポートデフォルト({パス、レンダリング})=>(
  <ルートコンテキスト.コンシューマー>
    {({currentPath}) => currentPath === パス && render()}
  </RouteContext.Consumer>
);

リンクの実装

エクスポートデフォルト({to、...props})=>(
  <ルートコンテキスト.コンシューマー>
    {({ onPopState }) => (
      <a
        href=""
        {...小道具}
        onClick={e => {
          e.preventDefault();
          window.history.pushState(null, "", to);
          ポップステート();
        }}
      />
    )}
  </RouteContext.Consumer>
);

Vue バージョンのフロントエンドルーティング実装

ハッシュベースの実装

操作効果:

5cb30fe18eb6118acce1f1720efb50c9.png

使用方法は vue-router に似ています (vue-router はプラグイン メカニズムを通じてルートを挿入しますが、これにより実装の詳細が隠されます。コードを直感的に保つために、ここでは Vue プラグインのカプセル化は使用されません)。

    <div>
      <ul>
        <li><router-link to="/home">ホーム</router-link></li>
        <li><router-link to="/about">について</router-link></li>
      </ul>
      <ルータービュー></ルータービュー>
    </div>
 
定数ルート = {
  '/家': {
    テンプレート: '<h2>ホーム</h2>'
  },
  '/について': {
    テンプレート: '<h2>概要</h2>'
  }
}
 
constアプリ = 新しいVue({
  el: '.vue.hash',
  コンポーネント:
    'ルータービュー': ルータービュー、
    'ルーターリンク': ルーターリンク
  },
  作成前() {
    this.$routes = ルート
  }
})

ルータビューの実装:

<テンプレート>
  <コンポーネント:is="routeView" />
</テンプレート>
 
<スクリプト>
'~/utils.js' から utils をインポートします
エクスポートデフォルト{
  データ () {
    戻る {
      ルートビュー: null
    }
  },
  作成された(){
    this.boundHashChange = this.onHashChange.bind(this)
  },
  マウント前() {
    window.addEventListener('hashchange', this.boundHashChange)
  },
  マウントされた(){
    onHashChange() は、
  },
  破棄する前に() {
    window.removeEventListener('hashchange', this.boundHashChange)
  },
  メソッド: {
    ハッシュ変更() {
      定数パス = utils.extractHashPath(window.location.href)
      this.routeView = this.$root.$routes[path] || null
      console.log('vue:hashchange:', パス)
    }
  }
}
</スクリプト>

ルータリンクの実装:

<テンプレート>
  <a @click.prevent="onClick" href=''><スロット></スロット></a>
</テンプレート>
 
<スクリプト>
エクスポートデフォルト{
  小道具: {
    から: 文字列
  },
  メソッド: {
    クリック時(){
      window.location.hash = '#' + this.to
    }
  }
}
</スクリプト>

履歴ベースの実装

操作効果:

f4708d3c19db588f48ae4dbc686b2d2e.png

使用方法は vue-router と似ています。

    <div>
      <ul>
        <li><router-link to="/home">ホーム</router-link></li>
        <li><router-link to="/about">について</router-link></li>
      </ul>
      <ルータービュー></ルータービュー>
    </div>
 
定数ルート = {
  '/家': {
    テンプレート: '<h2>ホーム</h2>'
  },
  '/について': {
    テンプレート: '<h2>概要</h2>'
  }
}
 
constアプリ = 新しいVue({
  el: '.vue.history',
  コンポーネント:
    'ルータービュー': ルータービュー、
    'ルーターリンク': ルーターリンク
  },
  作成された(){
    this.$routes = ルート
    this.boundPopState = this.onPopState.bind(this)
  },
  マウント前() {
    window.addEventListener('popstate', this.boundPopState) 
  },
  破棄前() {
    window.removeEventListener('popstate', this.boundPopState) 
  },
  メソッド: {
    onPopState (...引数) {
      this.$emit('popstate', ...引数)
    }
  }
})

ルータビューの実装:

<テンプレート>
  <コンポーネント:is="routeView" />
</テンプレート>
 
<スクリプト>
'~/utils.js' から utils をインポートします
エクスポートデフォルト{
  データ () {
    戻る {
      ルートビュー: null
    }
  },
  作成された(){
    this.boundPopState = this.onPopState.bind(this)
  },
  マウント前() {
    this.$root.$on('popstate', this.boundPopState)
  },
  破棄する前に() {
    this.$root.$off('popstate', this.boundPopState)
  },
  メソッド: {
    onPopState (e) {
      定数パス = utils.extractUrlPath(window.location.href)
      this.routeView = this.$root.$routes[path] || null
      console.log('[Vue] popstate:', パス)
    }
  }
}
</スクリプト>

ルータリンクの実装:

<テンプレート>
  <a @click.prevent="onClick" href=''><スロット></スロット></a>
</テンプレート>
 
<スクリプト>
エクスポートデフォルト{
  小道具: {
    から: 文字列
  },
  メソッド: {
    クリック時(){
      history.pushState(null, '', this.to)
      this.$root.$emit('popstate')
    }
  }
}
</スクリプト>

まとめ

フロントエンド ルーティングのコア実装原理は非常にシンプルですが、特定のフレームワークと組み合わせると、フレームワークによって動的ルーティング、ルーティング パラメーター、ルーティング アニメーションなどの多くの機能が追加され、ルーティングの実装が複雑になります。この記事は、フロントエンドルーティングのコア部分の実装のみを分析し、ハッシュモードと履歴モードに基づくネイティブ JS/React/Vue の 3 つの実装、合計 6 つの実装バージョンを参考として提供します。お役に立てば幸いです。

すべての例は Github リポジトリで入手できます: https://github.com/whinc/web-router-principle

参照する

シングルページルーティングのいくつかの実装原則の詳細な説明

シングルページアプリケーションルーティングの実装原則: React-Routerを例に

これで、React でブラウザの自動更新を実装するためのサンプルコードに関するこの記事は終了です。React ブラウザの自動更新に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript に基づいてブラウザが閉じられたか更新されたかを判断する (超正確)
  • JavaScriptはブラウザを更新せず、進むと戻る機能を実現しません。
  • WeChat ブラウザの Javascript が wi​​ndow.location.reload() を使用してページを更新できない問題の解決方法
  • ブラウザが閉じられているか更新されているかを判断するための Js インテリジェント コード
  • ブラウザのさまざまな更新ルールを深く理解する
  • ブラウザ更新データ消失問題を解決するvuex永続化プラグインの詳しい説明

<<:  VMware12.0 インストール Ubuntu14.04 LTS チュートリアル

>>:  SSDストレージを有効にしたMySQLインスタンスの詳細な説明

推薦する

Vueのアイデアを使ってストレージをカプセル化する方法

目次背景関数目的アイデアの源成し遂げるセット得るプロパティの削除拡張機能を禁止するもっている要約する...

CSS3ダイヤモンドパズルはdivのみを回転し、背景画像は回転しない機能を実現します

需要背景プロジェクトはVueを使用して作成され、ビジネス要件にはパズル効果があります。デフォルトの背...

MySQL ifnull のネスト使用手順

MySQL ifnull のネストされた使用ifnull をネストする方法があるかどうかオンラインで...

垂直方向の中央揃えをエレガントに実現する方法を教えます(推奨)

序文CSS で水平方向と垂直方向に中央揃えする方法はたくさんあります。この記事で紹介する方法は非常に...

Bootstrap 3.0 学習ノート CSS関連補足

この記事の主な内容は次のとおりです。 1. ブラウザのサポート2. 画像3. レスポンシブツール4....

MySQL データベースの基礎を始めるための一般的なコマンドの概要

この記事では、MySQL データベースの基礎を学ぶためによく使用されるコマンドを例を使って説明します...

Zabbixについて管理者ログインパスワードを忘れた場合、パスワードをリセットする

Zabbix 管理者ログイン パスワードのリセットに関する問題は次のとおりです。 1. 問題の説明:...

Tcl言語に基づくシンプルなネットワーク環境を構成するプロセスの分析

1. Tclスクリプトファイルcircle.tclコードコメント #シミュレーションに必要なプロパテ...

上下に空白行があるフォームを挿入する解決策

ウェブページを作成するときに、フォームを挿入した後、フォームの上下に空白行が表示されることがよくあり...

MySQLインジェクションバイパスフィルタリング技術の概要

まず、GIF 操作を見てみましょう。ケース1: スペースがフィルタリングされるスペースの代わりに角括...

Vue ミックスインの使用方法とオプションのマージの詳細な説明

目次1. コンポーネントでの使用2. オプションのマージ要約する1. コンポーネントでの使用Mixi...

シンプルな HTML ビデオ プレーヤーを実装する方法

この記事では、シンプルな HTML ビデオ プレーヤーを実装する方法を紹介し、皆さんと共有します。詳...

CSS でフローティングにより親要素の高さが崩れる問題を解決するいくつかの方法

以前は、フロートはレイアウトによく使用されていましたが、フローティングレイアウトを使用すると親要素の...

Vue ミックスインの使い方の詳しい説明

目次Vue ミックスインの使用ミックスインでのデータアクセスミックスイン/index.jsホーム.v...

Linux システムのデュアル ネットワーク カード バインディング構成の実装

システムバージョン [root@ ~]# cat /etc/redhat-release CentO...