react-router-dom
react-router-dom 是 react 的路由模块,本文介绍了 react-router-dom 的基本使用方法。
基本使用步骤:
- 安装:
yarn add react-router-dom - 在
src/index.js引入:import { Route, BrowserRouter } from 'react-router-dom' - 使用:用包裹需要使用路由的部分(例如:
render函数返回的标签)
BrowserRouter 组件和 Route 组件
BrowserRouter 和 Route 组件是 react-router-dom 的基本组件
BrowserRouter组件包裹需要使用路由的部分Route组件用于将路径与组件相关联
javascript
// src/index.js
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 导航组件:
javascript
// src/pages/Navbar.js
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、gopush用于跳转页面,会在页面栈尾部新增一条记录replace用于重定向页面,会将当前页面从页面栈中清除,不会留下痕迹go方法接受一个数字作为参数,例如go(-1)表示返回上一条路由记录
javascript
// src/pages/Contact.js
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 高阶组件:
javascript
// src/pages/Navbar.js
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 来获取
声明路由参数:
javascript
// src/index.js
// 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>获取路由参数:
javascript
// src/pages/PostDetail.js
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 })
})
}Hooks
react-router-dom 提供了一些钩子函数(hooks)来让你在函数组件中方便地使用路由功能。以下是一些常用的钩子函数:
useHistory():返回一个history对象,用于在函数组件中操作历史记录。例如,使用history.push('/path')可以实现路由跳转。useLocation():返回当前的location对象,可以用于在函数组件中获取当前的路由路径、查询参数等信息。useParams():返回一个包含当前路由参数的对象。例如,在路由路径为/users/:id的情况下,使用useParams().id可以获取当前用户的ID。useRouteMatch():返回一个包含当前路由匹配信息的对象。例如,可以使用useRouteMatch('/users/:id')来判断当前路由是否匹配/users/:id路径,并获取路由参数。
以下是一个使用 react-router-dom 钩子函数的示例:
jsx
import React from 'react';
import { BrowserRouter as Router, Route, Link, useHistory, useLocation, useParams, useRouteMatch } from 'react-router-dom';
function Users() {
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' },
];
return (
<div>
<h1>Users page</h1>
<ul>
{users.map(({ id, name }) => (
<li key={id}>
<Link to={`/users/${id}`}>{name}</Link>
</li>
))}
</ul>
<Route path="/users/:id" component={User} />
</div>
);
}
function User() {
const { id } = useParams();
const { pathname } = useLocation();
const { url } = useRouteMatch();
const history = useHistory();
function handleGoBack() {
history.goBack();
}
return (
<div>
<h2>User {id} page</h2>
<p>Current path: {pathname}</p>
<p>Matched URL: {url}</p>
<button onClick={handleGoBack}>Go back</button>
</div>
);
}
function App() {
return (
<Router>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
<Route exact path="/">
<h1>Home page</h1>
</Route>
<Route path="/users" component={Users} />
</Router>
);
}
export default App;在上面的代码中,我们使用了 useParams()、useLocation()、useRouteMatch() 和 useHistory() 等钩子函数来获取当前路由的参数、路径、匹配信息和历史记录对象,并在组件中使用它们实现了路由跳转、返回等功能。
湫的碎碎念