ブラウザの自動更新を実装する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インスタンスの詳細な説明

推薦する

Reactは無限ループスクロール情報を実装する

この記事では、無限ループスクロールを実現するためのReactの具体的なコードを参考までに紹介します。...

2008 年の Web デザインにおける 10 の経験

<br />インターネットは絶えず変化しており、BusinessWeek.com は専門...

生年月日を年齢に変換し、グループ化して人数を数えるMySQLの例

データベースのクエリ `学生`から*を選択 クエリ結果id名前誕生日1張三1970-10-01 2李...

MySQL イベント スケジューラに関するよくある話 (必読)

概要MySQL には独自のイベント スケジューラもあり、これは Linux の crontab ジョ...

私が遭遇したIE8の互換性に関する注意事項

1. IE8 の getElementById は id のみをサポートし、name はサポートしま...

Reactは適応性の高い仮想リストを実装する

目次変換前:変換後: 0x0の基本0x1 「固定高さ」の仮想リストを実装する原理:最適化: 0x2 ...

選択にスタイルを追加するための純粋な CSS (スクリプトなし) 実装

通常は ul、li を介して選択のデフォルト スタイルを変更して、実現をシミュレートします。このよう...

ES6分解課題の原理と応用

目次配列分割代入オブジェクトの分解代入分割割り当ての適用変数の値の交換関数から複数の値を返すマップ構...

Docker が占有するディスク領域をクリーンアップする方法

Docker は多くのスペースを占有します。コンテナを実行したり、イメージを取得したり、アプリケー...

css-loader を使用して vue-cli で css モジュールを実装する

【序文】 Vue と React の CSS モジュール ソリューションはどちらも、実装にローダーに...

React Stateの状態とライフサイクルの実装方法

1. コンポーネントの実装方法:組件名稱首字母必須大寫1. JS関数を通じてコン​​ポーネントを実装...

JavaScriptのURLオブジェクトとは何かについて話しましょう

目次概要ハッシュプロパティホストプロパティホスト名属性Href属性起源のプロパティユーザー名とパスワ...

MySQL でファイルデータをインポートする際の 1290 エラーの解決方法

エラーシナリオcmd の mysql コマンドを使用して、学生情報テーブルにデータを追加します。デー...

ウェブサイトのコードブロックのpreタグにコピーコードボタンコードを追加します

他のよりプロフェッショナルなブログ システムを参照すると、コード ブロックにコードのコピー ボタンが...

誤って削除されたデータを復元するための mysqlbinlog コマンドを使用した mysql の実装

実験環境: MYSQL 5.7.22バイナリログを有効にするログ形式 MIXED実験プロセス: 1....