点赞是美德 : )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