react-router
16796 ワード
静的経路と動的経路
react-router v 4は非常に大きなバージョンの変更であり、具体的には「静的経路」から「動的経路」への遷移に反映される.一般的には「静的ルーティング」を構成として考え、reactプロジェクトを開始すると、氏は良いルートテーブルになり、ページジャンプが発生すると、reactはアドレスによってルーティングテーブルに対応する処理ページまたは処理方法を見つける.動的ルーティングは、プロジェクトとして実行されるプロファイルとして外部に記憶されるのではなく、プロジェクトrenderの時に定義が開始される.routerの著者は、routeは他の一般的なコンポーネントと同じであるべきであり、ルーティング構成を提供するのではなく、通常のUIコンポーネントであると考える.これもreactの開発思想に合致しています.すべてのコンポーネントです.私自身は以前のバージョンのルートについてあまり知らないので、ここでは比較しません.興味のある仲間は自分で調べてみてもいいです.ここでロuterの作者がなぜこのような大きな変化をしたのかを説明します.
インストール
前に述べたように、webアプリケーションにはreact-router-domをインストールする必要があります.
でもnode_にいますmodulesの下で、相変わらずreact-routerの姿が見えます.これはreact-router-dom依存のカバンです.他にhistoryのカバンがあります.これは以下の通りです.
ルートの最外層を実現する容器です.一般的には直接にそれを使用する必要はありません.それに基づいてパッケージ化されたいくつかの異なる環境に適したコンポーネントを使用して、react-router-domのRouterは4つあります.
一般的にはあまり使われませんし、webアプリケーションではreact-router-domで拡張されたものと、この二つは前に述べた先端ルートの二つの解決方法のそれぞれの実現です.
后ろの配置に惑わされないように、実现のソースコードからルートを见てみます.
router.js createBrowserHistoryは現代ブラウザ(h 5 history API対応) に適用されます. createhashhistoryは、古いバージョンのブラウザに対応する必要がある場合に適用されます.
この2つの方法は、それぞれ2つのコンポーネントに対応しています.この2つの方法は、ヒットマンオブジェクトが持つ属性と同じですが、それぞれの実装が異なります.
だから、私達は直接に使うのと組み合わせてcreateBrowserHistoryを使うのと同じ効果です.
生成されたurlパスは、このように見える.
URLが/の時に、アプリの中のコンポーネントをレンダリングしたいと思います.しかしこの時、Appのrenderの中のthis.props.childrenはまだundefinedです.この場合は、デフォルトページを設定するためにIndexRouteを使用することができます.
UIをURLから結合させる
もし私たちが/inboxを/inbox/messages/:idから削除し、またMessageをApp->Inboxに組み込むことができたら、とてもいいです.絶対パスは私たちにこれをさせてくれます.
古いURLに対応しています
ちょっと待ってください.URLを変えました.これはよくないです今は誰でも訪問します./inbox/messages/5は間違ったページを見ます.(
心配しないでください.このURLを使って正常に動作させます.
入りと帰りのホク
Routeは、オン・Enterとone Leaveの2つのHookを定義することができ、これらのhookは、ページホッピングの確認時にトリガされます.これらのhookは、いくつかの場合には、権限認証や経路ホッピングの前に、いくつかのデータを永続的に保存するなど、非常に有用です.
ルーティング・ジャンプ中に、OneLeave Hookは、すべての離れたルートの中でトリガされ、最下層のサブルーティングから最外層の親ルーティングが終了するまで、その後、one Enter hookは最外層の親ルートから最下層の子ルーティングが終了するまで開始される.
上記の例を続けると、ユーザーがリンクをクリックすると、/messages/5から/aboutにジャンプします.以下はこれらのhookの実行順です. /message/:idのonLeave /inboxのonLeave /aboutのon Enter 代替の設定
routeは一般的にネストされているので、JSXという自然なネスト型文法の構造を使って、彼らの関係を説明するのはとても便利です.しかし、JSXを使いたくないなら、元のroute配列オブジェクトを直接使用することもできます.
上で議論したルーティング構成は以下のように書くことができます.
ルートは三つの属性を持っています.ネスト関係 パス文法 優先度 ネスト関係
React Routerは、指定されたURLが呼び出されたときに、セット中(命中部分)にレンダリングされます.入れ子ルートは、ツリー構造として記述されています.React Routerは、設定によって指定されたURLと一致するルートを探すために配置されています.
パス文法
ルートパスは、一つの(または一部)のURLに一致する文字列パターンであり、ほとんどのルートパスは、以下のいくつかの特殊な記号を除いて直接字面量で理解することができる.:paramName–マッチングする部分は、/、?または、菗後のURLにあります.命中した部分はパラメータ として使用されます.()–その内部の内容はオプションとされている –次の文字またはURLの最後まで任意の文字にマッチし、splatパラメータ を作成します.
優先度
最後に、ルーティングアルゴリズムは定義された順序によって下から下に向かってルーティングに一致します.したがって、2つの兄弟ルーティングノードの構成を持つ場合、前のルーティングが次のルーティングに一致しないことを確認してください.例えば、絶対にしないでください.
react-router v 4は非常に大きなバージョンの変更であり、具体的には「静的経路」から「動的経路」への遷移に反映される.一般的には「静的ルーティング」を構成として考え、reactプロジェクトを開始すると、氏は良いルートテーブルになり、ページジャンプが発生すると、reactはアドレスによってルーティングテーブルに対応する処理ページまたは処理方法を見つける.動的ルーティングは、プロジェクトとして実行されるプロファイルとして外部に記憶されるのではなく、プロジェクトrenderの時に定義が開始される.routerの著者は、routeは他の一般的なコンポーネントと同じであるべきであり、ルーティング構成を提供するのではなく、通常のUIコンポーネントであると考える.これもreactの開発思想に合致しています.すべてのコンポーネントです.私自身は以前のバージョンのルートについてあまり知らないので、ここでは比較しません.興味のある仲間は自分で調べてみてもいいです.ここでロuterの作者がなぜこのような大きな変化をしたのかを説明します.
To be candid, we were pretty frustrated with the direction we’d taken React Router by v2. We (Michael and Ryan) felt limited by the API, recognized we were reimplementing parts of React (lifecycles, and more),
and it just didn’t match the mental model React has given us for composing UI.
We ended up with API that wasn’t “outside” of React, an API that composed, or naturally fell into place,
with the rest of React.
, Route , react ,
, react (UI )。
react API , react API. route( , )
—— react-router
Webフロントエンドの開発において、私たちは常にページルートの問題を処理する必要があります.習慣的には、ルート情報は1つのところに集中して配置されます.私たちは「静的ルート」と呼ぶことができます.または「中心化ルート」と呼ばれます.react-router v 3バージョンを例にとって、コードは以下のようになります.import { Router, Route, IndexRoute, browserHistory } from 'react-router'
const App = () => (
history={browserHistory}>
"/" component={RootPage}>
"/users" component={UsersPage} />
)
render(, document.getElementById('app'))
プログラムの最上部のコンポーネントにすべてのルーティング情報が配置され、ネスト関係によって異なるレベルが具現されていることがわかる.しかし、react-router v 4バージョンは革命的に変更され、Reactの「構成要素化」思想により合致するようになりました.私たちは「動的ルート」と呼ぶことができます.またはブロックチェーンの用語を借りて「中心化ルート」と呼びます.v 4バージョンで書き換えたコードは以下のようになります.import { BrowserRouter, Route } from 'react-router-dom'
const App = () => (
)
const RootPage = () => (
"/" exact component={HomePage} />
"/users" component={UsersPage} />
)
render(, document.getElementById('app'))
ルーティングの構成は、トップのコンポーネントのすべてに位置するのではなく、異なるコンポーネントに分散され、コンポーネントのネスト関係によってルーティングのレベルが達成されることが分かる.また、静的なルーティングとは、事前にすべてのページを定義しているのとは異なり、動的なルーティングは、レンダリングの際に経路マッチング結果に基づいて、どのコンポーネントをレンダリングするかを動的に決定することができ、これにより、ページの多重化を十分に実現し、重複レンダリングを低減することができる.インストール
前に述べたように、webアプリケーションにはreact-router-domをインストールする必要があります.
でもnode_にいますmodulesの下で、相変わらずreact-routerの姿が見えます.これはreact-router-dom依存のカバンです.他にhistoryのカバンがあります.これは以下の通りです.
ルートの最外層を実現する容器です.一般的には直接にそれを使用する必要はありません.それに基づいてパッケージ化されたいくつかの異なる環境に適したコンポーネントを使用して、react-router-domのRouterは4つあります.
一般的にはあまり使われませんし、webアプリケーションではreact-router-domで拡張されたものと、この二つは前に述べた先端ルートの二つの解決方法のそれぞれの実現です.
后ろの配置に惑わされないように、実现のソースコードからルートを见てみます.
router.js
class Router extends React.Component {
//
static propTypes = {
history: PropTypes.object.isRequired, //
children: PropTypes.node
}
//
getChildContext() {
return {
router: {
...this.context.router,
history: this.props.history, //
route: {
location: this.props.history.location, //history location
match: this.state.match // , , 。
}
}
}
}
state = {
match: this.computeMatch(this.props.history.location.pathname)
}
computeMatch(pathname) {
return {
path: '/',
url: '/',
params: {}, //
isExact: pathname === '/'
}
}
}
この中で一番重要なのは、私たちが入ってきたhistoryオブジェクトが必要です.前に述べたように、私たちはコンポーネントを直接使用しないということです.このコンポーネントは私たちがhistoryオブジェクトに手動で入るように要求していますが、このオブジェクトは非常に重要です.また、開発環境によっては違ったhistoryが必要です.このような状況に対してreact-routerは2つのプラグインreact-router-domとreact-router-nativeを生み出しました.(これは比較的重要な理由だと思います.ブラウザにはhistoryオブジェクトがありますので、webアプリケーションのルートはすべてこのオブジェクトに基づいて拡張されています.).次に、react-router-domが使用するhistoryからの二つの方法を見てみましょう.この2つの方法は、それぞれ2つのコンポーネントに対応しています.この2つの方法は、ヒットマンオブジェクトが持つ属性と同じですが、それぞれの実装が異なります.
//createHashHistory.js
var HashChangeEvent = 'hashchange'; //hash
var createHashHistory = function createHashHistory() {
var globalHistory = window.history; // history
var handleHashChange = function handleHashChange() {} //hash
}
//createBrowserHistory.js
var PopStateEvent = 'popstate'; // url
var HashChangeEvent = 'hashchange'; // hash , hash , 。
var createBrowserHistory = function createBrowserHistory() {
var globalHistory = window.history; // history
var handlePop = function handlePop(location) {} //
}
//createHashHistory.js,createBrowserHistory.js history
const history = {
length: globalHistory.length, //globalHistory window.history
action: "POP", //
location: initialLocation, // !! Router.js , 。
createHref, // url , hash '#'
push, // history.pushState()
replace, // history.replaceState()
go, //history.go()
goBack, //history.back()
goForward, //history.forward()
block,
listen
}
コンソールから印刷してこのhistoryを見てみます.だから、私達は直接に使うのと組み合わせてcreateBrowserHistoryを使うのと同じ効果です.
import {
Router,
} from 'react-router-dom'
import createBrowserHistory from 'history/createBrowserHistory';
const history = createBrowserHistory();
const App = () => (
history={history}>
{/* */}
)
イコール:import {
BrowserRouter,
} from 'react-router-dom'
const App = () => (
{/* */}
)
使用上の注意点生成されたurlパスは、このように見える.
http://localhost:8080/#/user
hash値がサーバ端に届かないことを知っていますので、hashを使って記録状態を記録するにはサーバ側の協力が必要ではありません.http://localhost:8080/user
この時、このディレクトリの下でブラウザを更新すると、サーバー側にこのパスが設定されていないので、can't GET/userというエラーが発生します.解決方法は、devServerの配置を変更することです.devServer: {
publicPath: publicPath,
contentBase: path.resolve(__dirname, 'build'),
inline: true,
hot: true,
historyApiFallback: true, //
},
例import React from 'react'
import { Router, Route, Link } from 'react-router'
const App = React.createClass({
render() {
return (
App
- "/about">About
- "/inbox">Inbox
{this.props.children}
)
}
})
const About = React.createClass({
render() {
return About
}
})
const Inbox = React.createClass({
render() {
return (
Inbox
{this.props.children || "Welcome to your Inbox"}
)
}
})
const Message = React.createClass({
render() {
return Message {this.props.params.id}
}
})
React.render((
"/" component={App}>
"about" component={About} />
"inbox" component={Inbox}>
"messages/:id" component={Message} />
), document.body)
トップページを追加URLが/の時に、アプリの中のコンポーネントをレンダリングしたいと思います.しかしこの時、Appのrenderの中のthis.props.childrenはまだundefinedです.この場合は、デフォルトページを設定するためにIndexRouteを使用することができます.
import { IndexRoute } from 'react-router'
const Dashboard = React.createClass({
render() {
return Welcome to the app!
}
})
React.render((
"/" component={App}>
{/* url / Dashboard */}
"about" component={About} />
"inbox" component={Inbox}>
"messages/:id" component={Message} />
), document.body)
今、アプリのrenderの中のthis.props.childrenはこの元素です.この機能は、AppacheのDirectoryIndexおよびinxのindex命令に似ています.これらの機能は、要求されたURLがあるディレクトリにマッチするときに、indexと似たような入り口ファイルを作成することができます.UIをURLから結合させる
もし私たちが/inboxを/inbox/messages/:idから削除し、またMessageをApp->Inboxに組み込むことができたら、とてもいいです.絶対パスは私たちにこれをさせてくれます.
React.render((
"/" component={App}>
"about" component={About} />
"inbox" component={Inbox}>
{/* /messages/:id messages/:id */}
"/messages/:id" component={Message} />
), document.body)
多層ネストルーティングにおいて絶対経路を使用する能力は、URLに対して絶対的なコントロールを持たせる.私たちはURLに階層を追加する必要がなく、より簡潔なURLを使用することができます.古いURLに対応しています
ちょっと待ってください.URLを変えました.これはよくないです今は誰でも訪問します./inbox/messages/5は間違ったページを見ます.(
心配しないでください.このURLを使って正常に動作させます.
import { Redirect } from 'react-router'
React.render((
"/" component={App}>
"about" component={About} />
"inbox" component={Inbox}>
"/messages/:id" component={Message} />
{/* /inbox/messages/:id /messages/:id */}
"messages/:id" to="/messages/:id" />
), document.body)
今はクリックしている人がいます./inbox/messages/5このリンクは、彼らは自動的に/message/5にジャンプされます.入りと帰りのホク
Routeは、オン・Enterとone Leaveの2つのHookを定義することができ、これらのhookは、ページホッピングの確認時にトリガされます.これらのhookは、いくつかの場合には、権限認証や経路ホッピングの前に、いくつかのデータを永続的に保存するなど、非常に有用です.
ルーティング・ジャンプ中に、OneLeave Hookは、すべての離れたルートの中でトリガされ、最下層のサブルーティングから最外層の親ルーティングが終了するまで、その後、one Enter hookは最外層の親ルートから最下層の子ルーティングが終了するまで開始される.
上記の例を続けると、ユーザーがリンクをクリックすると、/messages/5から/aboutにジャンプします.以下はこれらのhookの実行順です.
routeは一般的にネストされているので、JSXという自然なネスト型文法の構造を使って、彼らの関係を説明するのはとても便利です.しかし、JSXを使いたくないなら、元のroute配列オブジェクトを直接使用することもできます.
上で議論したルーティング構成は以下のように書くことができます.
const routeConfig = [
{ path: '/',
component: App,
indexRoute: { component: Dashboard },
childRoutes: [
{ path: 'about', component: About },
{ path: 'inbox',
component: Inbox,
childRoutes: [
{ path: '/messages/:id', component: Message },
{ path: 'messages/:id',
onEnter: function (nextState, replaceState) {
replaceState(null, '/messages/' + nextState.params.id)
}
}
]
}
]
}
]
React.render(, document.body)
ルートマッチングの原理ルートは三つの属性を持っています.
React Routerは、指定されたURLが呼び出されたときに、セット中(命中部分)にレンダリングされます.入れ子ルートは、ツリー構造として記述されています.React Routerは、設定によって指定されたURLと一致するルートを探すために配置されています.
パス文法
ルートパスは、一つの(または一部)のURLに一致する文字列パターンであり、ほとんどのルートパスは、以下のいくつかの特殊な記号を除いて直接字面量で理解することができる.
"/hello/:name"> // /hello/michael /hello/ryan
"/hello(/:name)"> // /hello, /hello/michael /hello/ryan
"/files/*.*"> // /files/hello.jpg /files/path/to/hello.jpg
相対パスが使用されている場合、完全な経路は、そのすべての祖先ノードの経路と自身が指定した相対パスとによって連結されます.絶対パスを使用すると、ルーティングマッチング挙動は、ネスト関係を無視することができます.優先度
最後に、ルーティングアルゴリズムは定義された順序によって下から下に向かってルーティングに一致します.したがって、2つの兄弟ルーティングノードの構成を持つ場合、前のルーティングが次のルーティングに一致しないことを確認してください.例えば、絶対にしないでください.
"/comments" ... />
"/comments" ... />
転載先:https://juejin.im/post/5cde5f13f265da1bad56d30c