使用 React 路由:
- 安装:npm i react-router-dom
- 引入:import { Route, BrowserRouter } from 'react-router-dom'
- 使用:用包裹需要使用路由的部分(例如:render 函数返回的标签)
BrowserRouter 组件和 Route 组件:
import React, { Component } from 'react'
import Navbar from './components/Navbar'
import Home from './components/Home'
import About from './components/About'
import Contact from './components/Contact'
// 引入react路由
import { Route, BrowserRouter } from 'react-router-dom'
class App extends Component {
render () {
return (
// BrowserRouter 组件包裹需要使用路由的部分,Route 组件用于将路径与组件相关联
<BrowserRouter>
<div className="App">
<Navbar />
{/* exact 开启精准匹配,根路径必须开启此配置,否则只要匹配到带有 / 的路由都会显示出根路径页面 */}
<Route exact path="/" component={Home} />
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact} />
</div>
</BrowserRouter>
)
}
}
export default App
声明式导航
使用 Link 和 NavLink 导航组件:
import React from 'react';
// 引入react-router-dom 路由跳转组件 Link
import { Link, NavLink } from 'react-router-dom';
const Navbar = () => {
return (
<nav className="nav-wrapper red darken-3">
<div className="container">
<Link to="/" className="brand-logo">React路由</Link>
<ul className="right">
<li><Link to="/">Home</Link></li>
{/* Link 组件跳转时就只是跳转页面,NavLink 跳转时会在渲染出的 a 标签上加上 active 的 className */}
<li><NavLink to="/about">About</NavLink></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</div>
</nav>
)
}
export default Navbar
编程式导航
被 <BrowserRouter></BrowserRouter> 包裹的组件的 props 会默认传入 history、location 和 match 这三个对象,history 对象类似 bom(浏览器对象模型)中的 history对象;
history 对象中包含一些用于操作地址栏url的api,常用的有:push、replace、go
push 用于跳转页面,会在页面栈尾部新增一条记录
replace 用于重定向页面,会将当前页面从页面栈中清除,不会留下痕迹
go 方法接受一个数字作为参数,例如 go(-1) 表示返回上一条路由记录
import React from 'react';
const Contact = (props) => {
console.log(props)
setTimeout(() => {
// push 和 replace 的区别是:
// push 会在页面栈尾部添加新的页面,可以通过浏览器的返回按钮回到之前的页面
// replace 会从页面栈中删除当前的页面,再跳转到新的页面
props.history.push('/') // 跳转
props.history.replace('/') // 重定向
}, 2000)
return (
<div className="container">
<h3>Contact</h3>
</div>
)
}
export default Contact;
不被 <BrowserRouter></BrowserRouter> 包裹的组件的 props 中就不会有 history 路由对象,要想让这种组件中拥有路由对象,则可以使用 react-router-dom 中的 withRouter 高阶组件:
import React from 'react';
// 引入react-router-dom 路由跳转组件 Link
// 引入 withRouter 高阶组件并将组件作为参数导出后此组件才能使用 history api
import { Link, NavLink, withRouter } from 'react-router-dom';
const Navbar = ({ history }) => {
console.log(history)
return (
<nav className="nav-wrapper red darken-3">
<div className="container">
<Link to="/" className="brand-logo">React路由</Link>
<ul className="right">
<li><Link to="/">Home</Link></li>
{/* Link 组件跳转时就只是跳转页面,NavLink 跳转时会在渲染出的 a 标签上加上 active 的 className */}
<li><NavLink to="/about">About</NavLink></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</div>
</nav>
)
}
// 使用 withRouter 高阶组件后此组件将可以使用 history api
export default withRouter(Navbar)
路由传参
声明路由时使用 :xxx 的方式,然后在组件中通过 props.match.params.xxx 来获取
声明路由参数:
// BrowserRouter 组件包裹需要使用路由的部分,Route 组件用于将路径与组件相关联
<BrowserRouter>
<div className="App">
<Navbar />
{/* 被 Switch 包裹的路由只会渲染第一个匹配到的路径 */}
<Switch>
{/* exact 开启精准匹配,根路径必须开启此配置,否则只要匹配到带有 / 的路由都会显示出根路径页面 */}
<Route exact path="/" component={Home} />
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact} />
{/* id 表示路由参数 */}
<Route path="/:id" component={PostDetail} />
</Switch>
</div>
</BrowserRouter>
在组件中获取路由参数:
componentDidMount() {
const { match } = this.props
// 从 match 对象中获取路由参数
match.params.id && (this.setState({ id: match.params.id}))
axios.get('http://jsonplaceholder.typicode.com/posts/' + match.params.id)
.then(res => {
res.data && this.setState({ post: res.data })
})
}