在 react-router-dom 的官方教程中,一共給出12個示例,可是我的認爲,着12個示例看着真的很累人,不少寫法,不是標準的企業項目應用的寫法,因此針對這個現狀,我想用企業項目開發的要求,對教程中的每個示例進行重寫,這篇教程就是它的第一個示例——基本使用和介紹。css
<font color=#ff502c>react-router</font> 的工做方式,是在組件樹頂層放一個Router組件,而後在組件樹中散落着不少reactr
組件,頂層的Router組件負責分析監聽URL的變化,在它保護傘之下的Route組件能夠直接讀取這些信息。react
很明顯,Router和Route的配合,就是以前咱們介紹過的"提供者模式",Router是
<font color=#ff502c>"提供者"</font>
,Route是 <font color=#ff502c>"消費者"</font>。瀏覽器
Router其實也是一層抽象,讓下面的Route無需各類不一樣URL設計的細節,不要覺得
URL就一種設計方法,至少能夠分爲兩種。服務器
第一種:好比 / 對應 <font color=#ff502c>Home</font> 頁, /about對應<font color=#ff502c>about</font> 頁,可是這樣的設計須要服務器端渲染,
應爲用戶能夠直接訪問任何一個URL,服務器必須能對 / 的訪問返回HTML, 也要對 /about 的訪問返回HTML。react-router
第二種:只有一個路徑 / ,經過URL後面的 <font color=#ff502c>#</font> 部分來決定路由, <font color=#ff502c>/#/</font> 對應Home頁。
<font color=#ff502c>/#/about</font>
對應About頁。應爲URL種 # 以後的部分是不會發送給服務器的,因此,
不管哪一個URL,最後都是訪問服務器的 / 路徑,服務器也只須要返回同一份HTNL就能夠,而後由瀏覽器端解析 # 後的部分
,完成瀏覽器端渲染。dom
一個使用了 HTML5 history API 的高階路由組件,保證你的 UI 界面和 URL 保持同步。此組件擁有如下屬性:函數
爲全部位置添加一個基準URL.
使用場景:假如你須要把頁面部署到服務器的二級目錄,你可使用 basename 設置到此目錄。動畫
<BrowserRouter basename="/wsm" /> <Link to="/react" /> // 最終渲染爲 <a href="/minooo/react">
導航到此頁面前執行的函數,默認使用 window.confirm
使用場景:當須要用戶進入頁面前執行什麼操做時可用,不過通常用到的很少。this
const getConfirmation = (message, callback) => { const allowTransition = window.confirm(message) callback(allowTransition) } <BrowserRouter getUserConfirmation={getConfirmation('Are you sure?', yourCallBack)} />
做用:當瀏覽器不支持 HTML5 的 history API 時強制刷新頁面。
使用場景:同上。url
const supportsHistory = 'pushState' in window.history <BrowserRouter forceRefresh={!supportsHistory} />
做用:設置它裏面路由的 location.key 的長度。默認是6。(key的做用:點擊同一個連接時,每次該路由下的 location.key都會改變,能夠經過 key 的變化來刷新頁面。)
使用場景:按需設置。
<BrowserRouter keyLength={12} />
最後展現實例:
<BrowserRouter basename="/minooo" forceRefresh={false} getUserConfirmation={getConfirmation()} keyLength={12} ></BrowserRouter>
<Route> 自帶三個 render method 和三個 props 。
render methods 分別是:
props 分別是:
全部的 render method 無一例外都將被傳入這些 props。
只有當訪問地址和路由匹配時,一個 React component 纔會被渲染,此時此組件接受 route props (match, location, history)。
當使用component時,router將使用React.createElement根據給定的Component建立
一個新的React元素。這意味着若是你使用內聯函數傳值給component將會產生沒必要要的重複裝載。對於內聯渲染(inline rendering), 建議使用 render prop。
<Route path="/user/:username" component={User} /> const User = ({ match }) => { return <h1>Hello {match.params.username}!</h1> }
<font color=#ff502c> to: string</font>
做用:跳轉到指定路徑
使用場景:若是隻是單純的跳轉就直接用字符串形式的路徑。
<Link to="/courses" />
<font color=#ff502c> to: object</font>
做用:攜帶參數跳轉到指定路徑
做用場景:好比你點擊的這個連接將要跳轉的頁面須要展現此連接對應的內容,又好比這是個支付跳轉,須要把商品的價格等信息傳遞過去。
<Link to={{ pathname: '/course', search: '?sort=name', state: { price: 18 } }} />
這是 <Link> 的特殊版,顧名思義這就是爲頁面導航準備的。由於導航須要有 「激活狀態」。
<font color=#ff502c>activeClassName: string</font>
導航選中激活時候應用的樣式名,默認樣式名爲 active
<NavLink to="/about" activeClassName="selected" >MyBlog</NavLink>
只渲染出第一個與當前訪問地址匹配的 <Route> 或 <Redirect>。
當用戶離開當前頁面前作出一些提示。
當用戶離開當前頁面時,設置的提示信息。
<Prompt message="肯定要離開?" />
當用戶離開當前頁面時,設置的回掉函數
<Prompt message={location => ( `Are you sue you want to go to ${location.pathname}?` )} />
經過設置必定條件要決定是否啓用 Prompt
<Prompt when={this.state.dirty} message="數據還沒有保存,肯定離開?" />
match 對象包含了 <Route path> 如何與 URL 匹配的信息,具備如下屬性:
在如下情境中能夠獲取 match 對象
location 是指你當前的位置,將要去的位置,或是以前所在的位置
在如下情境中能夠獲取 location 對象
location 對象不會發生改變,所以能夠在生命週期的回調函數中使用 location 對象來查看當前頁面的訪問地址是否發生改變。這種技巧在獲取遠程數據以及使用動畫時很是有用
componentWillReceiveProps(nextProps) { if (nextProps.location !== this.props.location) { // 已經跳轉了! } }
能夠在不一樣情境中使用 location:
history 對象是可變的,由於建議從 <Route> 的 prop 裏來獲取 location,而不是從 history.location 直接獲取。這樣能夠保證 React 在生命週期中的鉤子函數正常執行,例如如下代碼:
class Comp extends React.Component { componentWillReceiveProps(nextProps) { // locationChanged const locationChanged = nextProps.location !== this.props.location // 錯誤方式,locationChanged 永遠爲 false,由於history 是可變的 const locationChanged = nextProps.history.location !== this.props.history.location } }
import React, { Component } from 'react'; import './App.css'; import { BrowserRouter as Router, Link, Route, Switch, } from 'react-router-dom'; import Home from './components/Home/Home' class App extends Component { render() { const About = ( ) => <h1>About</h1>; const Nested = () => ( <div> <Link to="/nested/one">One</Link> <Link to="/nested/two">Two</Link> <Link replace to="/nested/Three">Three</Link> <div>選擇一個點擊</div> <Route path="/nested/:minooo?" render={({match}) => <h2>URL: {match.params.minooo || 'minooo'}</h2>} /> </div> ) return ( <div className="App"> <Router> <Link to="/">Home</Link> <Link to={{ pathname: '/about',search:'?sort=name', state:{ price: 18 } }}>About</Link> <Link to="/contact/12?name=minooo">Contact</Link> <Link to="/blog">blog</Link> <Link to="/nested">Nested</Link> {/* <NavLink to="/about" activeClassName="active">MyBlog</NavLink> */} <main> <Switch> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/contact/:id" render={({ history, location, match }) => <h1> {console.log(history, location, match)} <span onClick={() => {history.push('/', {name:'mm'})}}>click me</span> </h1>} /> <Route path="/blog" children={({ match }) => ( <li className={match?'active': ''}> <Link to="/">User</Link> </li> )} /> <Route path="/nested" render={Nested} /> <Route render={() => <h1>Page not found</h1>} /> </Switch> </main> </Router> </div> ); } } export default App;