react-routerのルートブロッカー(ナビゲーションガード)を実装する方法
react-routerのルートインターセプトを自分で実装する前に、vueのルートインターセプトがどのように使われ、何をするのかを見てみましょう。
その名の通り ビューアルーター は、主にジャンプやキャンセルによるナビゲーションをガードするために使用されるナビゲーションガードを提供します。
グローバルガード
を使用することができます。 ルーター.beforeEach を使用して、グローバルな先行者ガードを登録します。
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
Copy the code
ナビゲーションがトリガーされると、グローバルな先行ガードが作成された順に呼び出されます。ガードはパースによって非同期に実行され、その時点でナビゲーションはすべてのガードに実行されます。 解決 はすべてのガードが終了するまで待機する。
ここで、vueはすべてのルートジャンプの前にbeforeEachでリスニングし、ルールにマッチすればジャンプし、そうでなければ指定した場所にジャンプすることがわかります。
react-routerで同じapiが提供されないのはなぜですか?に対して、作者はgithubで回答しています。
You can do this from within your render function. JSX doesn't need an API for this because it's more flexible.
Copy the code
おそらく、これが意味するところは
You can perform this operation in the rendering function. JSX does not require an API because it is more flexible.
Copy the code
リンク react-routerのルートインターセプトに関する公式説明書
作者の回答にあるように、彼はreact-routerを柔軟なものにしたいので、あまり多くのapiを追加したくはないようです。これらのapiは、ユーザーがニーズに応じて独自のルートインターセプトを実装できるようにするためのものです。ここでは、ほとんどのニーズを満たすルートインターセプターを実装する方法を説明します。
react-routerのバージョン。4.0
まず、react-router-configを使って、ルートの設定を配列の形で書きます。
//routerConfig.js
const routes = [
{
path: '/',
component: 'component/app',
routes: [
{
path: '/asd',
component: 'component/topics',
routes: [
{
path: '/asd/login',
component: 'component/home'
}
]
}
]
}
]
export default routes
Copy the code
コンフィギュレーションで書かれているのは、プロジェクト全体のルーティング構成を見て、どこにジャンプするのか、どのコンポーネントがどの位置の下に表示されるのかを正確に把握することが直感的にできるからです。
見ていただければわかると思いますが、この中でドキュメントと違うことを書いたのは2箇所です。
1. I have only one list item in the whole array, just this one object.
2. The value of my compoent is a string, not an object or method
Copy the code
最初のポイント:我々は現在のページでルートルートが必要な場合がありますので、ルートルートで、我々はおそらくテーマの色の設定、グローバルコンテンツの表示などで何かをしたい、ここで、我々はそれを行うことができます、残りのすべて、彼の中で ルート でOKです。
2点目。これを行う目的は、ルートの高速レンダリングを可能にすることであり、通常の使用では一般的に次のように行います。
//pseudo-code, for reference only
import A from '. /a'
{
path:'/',
component:A
}
Copy the code
基本的に、これはどのように実装されている、問題がある場合、私たちのページには、20、あるいは50、100のパスをジャンプするには、どのように、そのたびに我々は、ルータ.jsファイルに読み込むように、それは非常に多くのファイルをインポートする必要がある、これは非常にコードの実行効率とページの描画速度に影響を与えることである。
以下、レンダリング方法について詳しく説明します。
ルートは全体として配列なので、ここでループを通過することになりますが、もしこれを最も不格好な方法で行えば
<Route path='/' component={a} />
<Route path='/b' component={b} />
<Route path='/c' component={c} />
<Route path='/d' component={d} />
...
Copy code
もちろん、この方法でルートジャンプを実装するのは賢明ではありません。メンテナンスしやすく、読みやすいルートを書きたいのです。
そこで、ここではルートの配列を繰り返し処理するメソッドを書きました。
//renderRoutesMap.js
import RouterGuard from '. /routerGuard'
const renderRoutesMap = (routes) => (
routes.map((route, index) => {
return (
<Route key={index} path={route.path} render={props => (
<RouterGuard {... .route} {. .props} />
)}
/>
)
})
)
export default renderRoutesMap
Copy the code
ここでルートのレンダリングを少しトラバースして、ルートオブジェクトを取って一度だけ通過します、ここでキッカーが登場します!
RouterGuardは、私たちの焦点です。ここでは、実際のルートブロック(ナビゲーションガード)を行うつもりです!
//routerGuard.js import React, { Component } from 'react' import { withRouter } from 'react-router-dom' import Loadable from 'react-loadable' import { connect } from 'react-redux' import renderRoutesMap from '. /renderRoutesMap' const mapStateToProps = state => (state) const mapDispatchToProps = dispatch => ({ . .dispatch }) class RouterGuard extends Component { constructor(props) { super() } componentWillMount() { let { history: { replace }, authorization, location } = this.props if (authorization) replace('. /login') if (location.pathname === '/') replace('. /asd') console.log('Interception before route jump', this.props) } render() { let { component, routes = [] } = this.props console.log('ready to render before compoent', this.props) const LoadableComponent = Loadable({ loader: () => import(`. /${component}`), loading: () => ( 11111 ) }) return (
) } } export default withRouter(connect(mapStateToProps, mapDispatchToProps)(RouterGuard)) Copy the code{renderRoutesMap(routes)} //renderRoutes.js import renderRoutesMap from '. /renderRoutesMap' /** * renderRoutes render routes * @param {array} routes route list * @param {object} extraProps = {} properties of extra * @param {object} switchProps = {} the properties of switch */ const renderRoutes = ({ routes, extraProps = {}, switchProps = {} }) => (
) export default renderRoutes //index.js const router = () => ( renderRoutes({ routes: routerConfig }) ) export default router Copy the code {renderRoutesMap(routes)}
ここでは、実際に私のプロジェクトで使われているコードなので、react-reduxが入っているので、reduxを使っていない場合は分解してください。
componentWillMountはreactコンポーネントのライフサイクルで、レンダリング前に呼び出され、reduxからの引数と、ルートから持ってきた引数を取得することができます。
ここでは、authorizationを使っているので、authorizationがtrueの場合、ログインしていないことを意味し、ログインページにジャンプしています。
また、ルートルートにいるときに、別のアドレスにジャンプするようにリダイレクトも行っています。
これで実は真のルート遮断ができるのですが、それだけでは不十分で、できるだけ高速にレンダリングし、ユーザー体験を向上させるためには、遮断にプラスして行わなければならないのです。
ここでは ローダブル プラグインを使用します。これは、動的にインポートされたコンポーネントで上位のコンポーネントをロードし、ユーザーエクスペリエンスを向上させるために使用します。
importは変数をサポートしないので、ここではテンプレートストリングのアプローチを使っています。コンポーネントを入力してレンダリングの準備をするたびにインポートするだけなので、レンダリングのたびにリソースを浪費する必要がなく、最初のレンダリングを確実に速くすることができます。
最後に、ルート設定、ルート配列のレンダリング、ルートコンポーネントのレンダリングをつなぎ合わせて、react-router全体のルートインターセプト(ナビゲーションガード)とします。
<ルーター
<スイッチ
{renderRoutesMap(routes)}となります。
最後に、ページ内で、index.jsを導入すれば完了です。
私が勉強や仕事で使っている方法なので、間違っているところがあればご指摘いただければと思います。最後に、いいね!やフォローをいただけると嬉しいです、ありがとうございます。
関連
-
[解決済み】Uncaught SyntaxError: JSON.parseで予期しないJSON入力の終了(<匿名>)
-
[解決済み】JavaScriptで「無効な日付」のDateインスタンスを検出する
-
[解決済み] javascriptのルックアップテーブルを作成する簡単な方法はありますか?
-
[解決済み] Syntax error : await is only valid in async function を解決するにはどうすればよいですか?
-
[解決済み] DIVコンテンツを更新する方法を教えてください。
-
[解決済み] Javascriptのクラスを使ってテーブルの行を表示/非表示にする
-
[解決済み] create-react-appのcontent-dispositionヘッダが表示されない [重複].
-
[解決済み] d3.js v4 timeParse()が動作しない?
-
[解決済み] JavaScriptでwindow.location(URL)からハッシュを削除する方法 ページを更新せずに?
-
js error null のプロパティ 'getAttribute' を読み取れません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】ループ内に関数を作らない【重複あり
-
[解決済み] Googleマップのズームレベルの設定方法
-
[解決済み] TypeError: Node' の 'appendChild' の実行に失敗しました: パラメータ 1 は 'Node' のタイプではありません。
-
[解決済み] 大きなHTML文字列からjQueryオブジェクトを作成する
-
[解決済み] 1:1 エラー 構文解析エラーです。予期しない文字 '�' があります。
-
[解決済み] jqGridの隠しカラム
-
[解決済み] alert("Hi!") と function(){alert("Hi!")} の違い。重複] [重複] [重複] [重複] [重複] [重複
-
[解決済み] select onChange がフォーム内で動作しない
-
[解決済み] JavaScript/jQueryでリダイレクト時にPOSTデータを送信する?[重複)。
-
[解決済み] UnderscoreJSを使用して配列から項目を削除する