點贊是美德 : )css
經過官網咱們能夠發現 react-router
能夠用在 web 網站端
native 設備端
html
咱們這裏針對 web 網站端
安裝前端
yarn add react-router-dom
複製代碼
react-router
會包自動依賴安裝html5
import React, {Component} from 'react'
import {HashRouter as Router, Route, Link, Switch} from 'react-router-dom'
const Home = () => (
<div> <h2>首頁</h2> </div>
)
const About = () => (
<div> <h2>關於</h2> </div>
)
class RouterView extends Component {
render() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">首頁</Link>
</li>
<li>
<Link to="/about">關於</Link>
</li>
</ul>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</div>
</Router>
)
}
}
export default RouterView
複製代碼
最外層須要包裹組件
<Router>
組件<Route>
就是你看到的組件內容,放在哪裏就哪裏顯示 組件<Link>
是頁面連接react
https://codepen.io/ducafecat/pen/GdBPqZgit
BrowserRouter
仍是 HashRouter
BrowserRouter
是須要服務端配合, 是基於html5的pushState和replaceState的,不少瀏覽器不支持,存在兼容性問題。連接地址長這樣
http://localhost:3000/about
github
HashRouter
是瀏覽器端解析路由連接地址長這樣
http://localhost:3000#/about
web
import {HashRouter as Router, Route, Link, Switch} from 'react-router-dom'
//import {BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom'
<Router>
...
</Router>
複製代碼
我用
as Router
作了別名,方便切換redux
<Route>
屬性 exact
徹底匹配<Route path="/about" component={About} />
複製代碼
exact=false
的時候 path
等於 /about
/about/me
都能匹配segmentfault
可是 exact=true
的時候 只匹配 path
等於 /about
<Route>
屬性 strict
末尾斜槓的匹配<Route strict path="/about/" component={About} />
複製代碼
當 strict=true
路由請求末尾必須帶 /
<Link>
生成路由連接
to: string
路由地址字符串
<Link to="/about?me=haha">關於</Link>
複製代碼
to: object
路由對象
<Link to={{
pathname: '/courses',
search: '?sort=name',
hash: '#the-hash',
state: { fromDashboard: true }>關於</Link>
複製代碼
replace: bool
設置 true
替換瀏覽器對象 history
爲當前路由,按回退按鈕時會發現以前的路由被替換了
<NavLink>
生成路由連接的基礎上,若是是當前路由設置激活樣式
activeClassName: string
樣式名稱
<NavLink to="/about" activeClassName="selected">關於</NavLink>
複製代碼
activeStyle: object
樣式對象
<NavLink to="/about" activeStyle={{
fontWeight: 'bold',
color: 'red'
}}>關於</NavLink>
複製代碼
isActive: func
判斷函數
const checkIsActive = (match, location) => {
if (!match) {
return false
}
...
return true
}
<NavLink to="/about" isActive={checkIsActive}>關於</NavLink>
複製代碼
<Switch>
只渲染出第一個與當前訪問地址匹配的 <Route>
或 <Redirect>
不然你有幾個 <Route>
都會顯示
<Redirect>
路由重定向
<Switch>
<Redirect from='/users/:id' to='/users/profile/:id'/> <Route path='/users/profile/:id' component={Profile}/> </Switch> 複製代碼
當請求 /users/:id
被重定向去 '/users/profile/:id'
from: string
須要匹配的將要被重定向路徑。
to: string
重定向的 URL 字符串
to: object
重定向的 location 對象
push: bool
若爲真,重定向操做將會把新地址加入到訪問歷史記錄裏面,而且沒法回退到前面的頁面。
<Prompt>
當用戶離開當前頁面前作出一些提示。
message: string
當用戶離開當前頁面時,設置的提示信息。<Prompt message="肯定要離開?" />
複製代碼
message: func
當用戶離開當前頁面時,設置的回掉函數
<Prompt message={location => `肯定要去 ${location.pathname} ?`} />
複製代碼
when: bool
決定是否啓用 Prompt
<Route path="/topics/:topicId" component={Topic} />
複製代碼
:topicId
定義參數
const Topic = ({match}) => (
<div> <h3>參數: {match.params.topicId}</h3> </div>
)
複製代碼
match.params
就是傳遞的參數
代碼
import React, {Component} from 'react'
import {BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom'
const Topic = ({match}) => (
<div> <h3>參數: {match.params.topicId}</h3> </div>
)
class RouterView extends Component {
render() {
return (
<Router> <div> <ul> <li> <Link to="/topics/rendering">Rendering with React</Link> </li> <li> <Link to="/topics/components">Components</Link> </li> <li> <Link to="/topics/props-v-state">Props v. State</Link> </li> </ul> <Switch> <Route path="/topics/:topicId" component={Topic} /> </Switch> </div> </Router> ) } } export default RouterView 複製代碼
動圖效果
代碼
import React, {Component} from 'react'
import {BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom'
const Back = () => (
<div> <h2>首頁</h2> </div>
)
const NoMatch = () => (
<div> <h2>沒有匹配</h2> </div>
)
class RouterView extends Component {
render() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/back">返回</Link>
</li>
<li>
<Link to="/also/will/not/match">路由請求</Link>
</li>
</ul>
<Switch>
<Route path="/back" component={Back} />
<Route component={NoMatch} />
</Switch>
</div>
</Router>
)
}
}
export default RouterView
複製代碼
在最下面寫個默認組件,都沒命中,就是這個了
動圖效果
在 react-route4
中嵌套要這樣寫
<Switch>
<Route path="/article" component={ArticleList} />
<Route path="/article/:id" component={Article} />
<Route path="/article/:id/recommend" component={ArticleRecommend} />
</Switch>
複製代碼
寫成一排,業務以下
path | 組件 | 說明 |
---|---|---|
/article | ArticleList | 文章列表 |
/article/:id | Article | 文章 |
/article/:id/recommend | ArticleRecommend | 文章推薦 |
適合用來作權限檢查
Route
const isAuthenticated = true
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
複製代碼
...
<Route path="/public" component={Public} />
<Route path="/login" component={Login} />
<PrivateRoute path="/protected" component={Protected} />
複製代碼
這裏用到了 react-transition-group
庫
動圖效果
yarn add react-transition-group
複製代碼
css
文件 fade.css
.fade-enter {
opacity: 0;
z-index: 1;
}
.fade-enter-active {
opacity: 1;
transition: opacity 250ms ease-in;
}
.fade-exit {
opacity: 0;
}
複製代碼
名稱 | 說明 |
---|---|
fade-enter | 動畫啓動 |
fade-enter-active | 動畫激活 |
fade-exit | 動畫離開 |
其它動畫樣式名字能夠參考 css-transition
...
import {TransitionGroup, CSSTransition} from 'react-transition-group'
import './fade.css'
複製代碼
TransitionGroup, CSSTransition
必須導入
const styles = {}
styles.fill = {
position: 'relative',
height: '200px',
width: '500px'
}
styles.content = {
...styles.fill,
top: '40px',
textAlign: 'center',
height: '120px'
}
styles.nav = {
padding: 0,
margin: 0,
position: 'absolute',
top: 0,
height: '40px',
width: '100%',
display: 'flex'
}
styles.navItem = {
textAlign: 'center',
flex: 1,
listStyleType: 'none',
padding: '10px'
}
styles.hsl = {
color: 'white',
paddingTop: '20px',
fontSize: '30px',
height: '120px'
}
styles.rgb = {
color: 'white',
paddingTop: '20px',
fontSize: '30px',
height: '120px'
}
複製代碼
這是 react
的樣式對象,固然你也能夠寫成 .css
文件
const NavLink = props => (
<li style={styles.navItem}> <Link {...props} style={{color: 'inherit'}} /> </li> ) 複製代碼
// 切換區域 A
const HSL = ({match: {params}}) => (
<div style={{ ...styles.fill, ...styles.hsl, background: `hsl(${params.h}, ${params.s}%, ${params.l}%)` }} > hsl({params.h}, {params.s}%, {params.l}%) </div>
)
// 切換區域 B
const RGB = ({match: {params}}) => (
<div style={{ ...styles.fill, ...styles.rgb, background: `rgb(${params.r}, ${params.g}, ${params.b})` }} > rgb({params.r}, {params.g}, {params.b}) </div>
)
複製代碼
const RouterView = () => (
<Router>
<Route
render={({location}) => (
<div style={styles.fill}>
<Route
exact
path="/"
render={() => <Redirect to="/hsl/10/90/50" />}
/>
<ul style={styles.nav}>
<NavLink to="/hsl/10/90/50">Red</NavLink>
<NavLink to="/hsl/120/100/40">Green</NavLink>
<NavLink to="/rgb/33/150/243">Blue</NavLink>
<NavLink to="/rgb/240/98/146">Pink</NavLink>
</ul>
<div style={styles.content}>
<TransitionGroup>
<CSSTransition key={location.key} classNames="fade" timeout={300}>
<Switch location={location}>
<Route exact path="/hsl/:h/:s/:l" component={HSL} />
<Route exact path="/rgb/:r/:g/:b" component={RGB} />
<Route render={() => <div>Not Found</div>} />
</Switch>
</CSSTransition>
</TransitionGroup>
</div>
</div>
)}
/>
</Router>
)
複製代碼
https://codepen.io/ducafecat/pen/rvroYP