React Router包含了四个包
包名 | Description |
---|---|
react-router | React Router核心api |
react-router-dom | React Router的DOM绑定,在浏览器中运行不需要额外安装react-router |
react-router-native | React Native 中使用,而实际的应用中,其实不会使用这个。 |
react-router-config | 静态路由的配置 |
主要使用`react-router-dom
1.声明式路由
import React, { Component } from 'react'
import { BrowserRouter as Router, Route, NavLink} from 'react-router-dom'
import './style.css'
const Home = () => <div>首页</div>
const Kind = () => <div>分类</div>
const Cart = () => <div>购物车</div>
const User = () => <div>我的</div>
export default class App extends Component {
render() {
// children --- 所有的路由都会渲染该路由对应的组件
// React路由声明式跳转 Link NavLink
return (
<Router>
<ul>
<li><NavLink activeClassName="selected" to="/home">首页</NavLink></li>
<li><NavLink activeClassName="selected" to="/kind">分类</NavLink></li>
<li><NavLink activeClassName="selected" to="/cart">购物车</NavLink></li>
<li><NavLink activeClassName="selected" to="/user">我的</NavLink></li>
</ul>
<hr />
//渲染组件的方式
<Route path="/home" component = { Home } />
<Route path="/kind" ><Kind /></Route>
<Route path="/cart" render = { () => <Cart/> }></Route>
<Route path="/user" component = { User } />
{/* <Route path="/user" children = { () => <User/> }></Route> */}
</Router>
)
}
}
2.编程式路由
...
// 编程式导航需要 使用 this.props.history 对象
// 如果当前组件没有的话,可以引入 withRouter --- 高阶组件
@withRouter
class App extends Component {
state = {
currentIndex: 0
}
changePage = (path, index) => {
return (e) => {
this.setState({ currentIndex: index })
this.props.history.push(path)
}
}
render() {
const { currentIndex } = this.state
// 编程式跳转
return (
<>
<ul>
<li className={ currentIndex === 0 ? 'active' : ''} onClick={ this.changePage('/home', 0) }>首页</li>
<li className={ currentIndex === 1 ? 'active' : ''} onClick={ this.changePage('/kind', 1) }>分类</li>
<li className={ currentIndex === 2 ? 'active' : ''} onClick={ this.changePage('/cart', 2) }>购物车</li>
<li className={ currentIndex === 3 ? 'active' : ''} onClick={ this.changePage('/user', 3) }>我的</li>
</ul>
...
</>
)
}
}
3.动态路由(路由传参)
const Child = (props) => {
console.log(props)//路由参数
const type = props.match.params.type
return (
<div>
child - { type }
</div>
)
}
class App extends Component {
render() {
return (
<>
...
<Route path="/:type" component = { Child } />
</>
)
}
}
4.二级路由
import React, { Component } from 'react'
import { Route, NavLink, useRouteMatch } from 'react-router-dom'
import './style.css'
// 嵌套路由
// 分类下的 导航组件
const Phone = () => <div>手机</div>
const Wash = () => <div>洗衣机</div>
const Ice = () => <div>电冰箱</div>
// 默认的导航组件
const Home = () => <div>首页</div>
const Cart = () => <div>购物车</div>
const User = () => <div>我的</div>
const Kind = () => {
console.log(useRouteMatch())
const { url } = useRouteMatch() // useRouteMatch只能在函数式组件中使用
return (
<div>
分类
<ul>
<li><NavLink to={ `${ url }/phone`}>大哥大</NavLink></li>
<li><NavLink to={ `${ url }/wash`}>洗衣机</NavLink></li>
<li><NavLink to={ `${ url }/ice`}>电冰箱</NavLink></li>
</ul>
<hr />
<Route path={ `${ url }/phone`} component = { Phone } />
<Route path={ `${ url }/wash`} component = { Wash } />
<Route path={ `${ url }/ice`} component = { Ice } />
</div>
)
}
class App extends Component {
render() {
return (
...
)
}
}
5.路由的重定向及精纯匹配
import { Route, NavLink, useRouteMatch, Redirect, Switch, withRouter } from 'react-router-dom'
...
@withRouter
class App extends Component {
render() {
const pathname = '/' + this.props.location.pathname.split('/')[1]
return (
<>
...
{/* Switch 只能选择其中一个路由 */}
<Switch >
<Route path="/home" component = { Home } />
<Route path="/kind" component = { Kind } />
<Route path="/cart" component = { Cart } />
<Route path="/user" component = { User } />
{/* exact 精准匹配 只有当路由为 / 时,才会重定向 */}
<Redirect path="/" exact to="/home" />
{/* 404路由配置在最底下 */}
<Route path="*" component = { NoMatch } />
</Switch>
</>
)
}
}
6.组件的递归调用
import React from 'react'
import { Switch, Route, Link, Redirect, useParams, useRouteMatch} from 'react-router-dom'
// 组件的递归调用 --- 不常见
const list = [
{ id: 0, name: '张三', friends: [1, 2]},
{ id: 1, name: '李四', friends: [0, 2]},
{ id: 2, name: '王五', friends: [0, 1, 3]},
{ id: 3, name: '麻六', friends: [0]}
]
const find = (id) => {
return list.find( item => item.id === id)
}
const Person = (props) => {
const { url } = useRouteMatch() // this.props.match
// console.log(url)
const { id } = useParams() // this.props.match.params
const person = find(id*1)
return (
<>
{ person.name } 的朋友有:
<ul>
{
person.friends.map((id, index) => {
let per = find(id*1)
return (
<li key = { index }>
<Link to={ `${url}/${ id }`}>
{ per.name }
</Link>
</li>
)
})
}
</ul>
{/* 形成了组件的递归调用 */}
<Route path={ `${url}/:id`} component={Person}/>
</>
)
}
const App = () => {
return (
<Switch>
<Route path='/:id' component={Person}/>
<Redirect path="/" exact to="/0" />
</Switch>
)
}
export default App