react-router-dom简介(推荐)
作者:wallowyou
react-router-dom
react-router-dom文档地址: https://reacttraining.com/react-router/
1. 安装
react-router提供多个包可以单独使用
package | description |
---|---|
react-router | 路由核心功能 |
react-router-dom | 基于react-router提供在浏览器运行环境下功能 |
react-router-native | for React Native |
react-router-config | static route congif helpers |
在浏览器中运行只需要安装react-router-dom,reac-router-dom依赖react-router会自动安装依赖,所以不需要再手动安装react-router
npm install react-router-dom -S // 或者 yarn add react-router-dom
2. 路由组件
react-router包含三种类型的组件:路由组件、路由匹配组件 、导航组件。在你使用这些组件的时候,都必须先从react-router-dom引入。
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
2.1 路由组件
react-router提供了两种路由组件: BrowserRouter
, HashRouter
其中BrowserRouter
是基于HTML5 history API (pushState
, replaceState
, popstate
)事件
当然与之对应的还有HashRouter
是基于window.location.hash
。
2.2 路由匹配组件
路由匹配组件有两种:Route
和Switch
,Switch
把多个路由组合在一起。
对于一个<Route>
组件,可以设置三种属性:component
、render
、children
来渲染出对应的内容。
当组件已存在时,一般使用component属性当需要传递参数变量给组件时,需要使用render属性
2.3 导航组件
有三种常用的导航组件,分别是:<Link>
、<NavLink>
、<Redirect>
。<NavLink>
是一种特殊的Link组件,匹配路径时,渲染的a标签带有active。
3. 使用
在需要使用router的地方引入react-router-dom
3.1 基本使用
以下是路由的基本使用例子
import React from 'react'; import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom"; // import logo from './logo.svg'; import './App.css'; import About from './views/About' import Home from './views/Home' import Person from './views/Person' function App() { return ( <Router> <div> <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> <li> <Link to="/person">Person</Link> </li> </ul> </nav> {/* A <Switch> looks through its children <Route>s and renders the first one that matches the current URL. */} <Switch> <Route path="/about"> <About /> </Route> <Route path="/person"> <Person /> </Route> <Route path="/"> <Home /> </Route> </Switch> </div> </Router> ); } export default App;
当然此处路由也可以有其他写法,比如
<Switch> <Route exact path="/" component={Home}></Route> <Route path="/about" component={About}></Route> <Route path="/person/:id" component={Person}></Route> <Route component={NotFind}></Route> </Switch>
其中的exact
表示的是精确匹配,比如上面
<Route exact path="/" component={Home}></Route>
如果没有写精确匹配的化,那么后面的所有路径都可以匹配到首页,解决方式就是增加exact或者将此路由放置最后面。
3.2 Route动态传参
在一个路由匹配组件上设置参数,比如说上面的Person组件
<Route path="/person/:id" component={Person}></Route>
设置是以:开始然后紧跟key值,然后我们在Person组件中就可以通过获取props获取这个参数值
import React from 'react'; export default class Person extends React.Component { constructor(props) { super(props); console.log(this.props.match.params.id) } render() { const id = this.props.match.params.id return ( <div> <h2>个人中心页面</h2> <p>个人id是:{id}</p> </div> ) } }
以上为传统class组件的写法,现在可以使用hooks,可以使用useParams
,代码如下:
import React from 'react'; import { useParams } from 'react-router-dom' const Person = () => { const { id } = useParams(); return ( <div> <h2>个人中心页面</h2> <p>个人id是:{id}</p> </div> ) }
3.3 嵌套路由
在About页面有一个嵌套路由代码示例:
import React from 'react'; import { Link, Switch, Route } from 'react-router-dom' import Tshirt from './product/Tshirt'; import Jeans from './product/Jeans' export default class About extends React.Component { constructor(props) { super(props) console.log(this.props.match) } render() { const match = this.props.match; return ( <> <nav> <Link to={`${match.url}/tshirt`}>Tshirt</Link>| <Link to={`${match.url}/jeans`}>Jeans</Link> </nav> <Switch> <Route path={`${match.path}/tshirt`} component={Tshirt}></Route> <Route path={`${match.path}/jeans`} exact component={Jeans}></Route> </Switch> </> ) } }
此处如果换成Function的话可以直接使用另一个钩子函数useRouteMatch
,获取当前匹配的路径和路由
import { useRouteMatch } from 'react-router-dom' const About = () => { const { path, url } = useRouteMatch(); ...省略 }
3.4 路由重定向
Redirect
路由重定向,使路由重定向到某个页面,比如我们经常会做的没有登录重定向到登录页面
<Route exact path="/"> {loggedIn ? <Redirect to="/dashboard" /> : <PublicHomePage />}</Route>
3.5 滚动还原
大部分情况下,我们需要的是每次导航到某个新页面的的时候,滚动条都是在顶部,这种比较好实现
hooks版本
import { useEffect } from "react";import { useLocation } from "react-router-dom"; export default function ScrollToTop() { const { pathname } = useLocation(); useEffect(() => { window.scrollTo(0, 0); }, [pathname]); return null; }
class版本
import React from "react";import { withRouter } from "react-router-dom"; class ScrollToTop extends React.Component { componentDidUpdate(prevProps) { if ( this.props.location.pathname !== prevProps.location.pathname ) { window.scrollTo(0, 0); } } render() { return null; }}
我们需要把ScrollToTop
组件放在Router里面eg:
function App() { return ( <Router> <ScrollToTop /> <App /> </Router> );}
而对于某些情况下比如一些tab我们希望切换回我们浏览过的tab页时我们希望滚动条滚动到我们之前浏览的位置,此处自行去实现。
3.6 路由守卫
有时候我们在某个表单页面填好了表单,然后点击跳转到另外一个页面。
这时候我们就需要提醒用户有未提交的表单。当然这一步其实也是在实际的业务代码中实现。
import React, { useState } from "react"; import { Prompt } from "react-router-dom"; const BlockingForm = ()=>{ let [isBlocking, setIsBlocking] = useState(false); return ( <form onSubmit={event => { event.preventDefault(); event.target.reset(); setIsBlocking(false); }} > <Prompt when={isBlocking} message={location => `你是否要跳转到 ${location.pathname}` } /> <p> Blocking?{" "} {isBlocking ? "Yes, click a link or the back button" : "Nope"} </p> <p> <input size="50" placeholder="输入值测试路由拦截" onChange={event => { setIsBlocking(event.target.value.length > 0); }} /> </p> <p> <button>提交表单模拟接触拦截</button> </p> </form> ); } export default BlockingForm;
3.7代码分割
有时候为了避免文件过大加快加载速度,我们需要将代码分割,将某些路由对应的组件只有在点击的时候再加载js,就是组件的懒加载。
我们使用webpack
, @babel/plugin-syntax-dynamic-import
,loadable-components
实现代码分割。
首先在.babelrc文件中增加配置
{ "presets": ["@babel/preset-react"], "plugins": ["@babel/plugin-syntax-dynamic-import"] }
在我们需要懒加载的组件使用loadabel
import React from 'react'; import loadable from '@loadable/component'; const BlockForm = loadable(() => import('../pages/BlockForm/index'), { fallback: <Loading /> })
其中BlockForm为懒加载得组件loadable
参考文档地址 跳转
3.8 withRouter
您可以通过withRouter高阶组件访问history属性和匹配的Route,
withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
eg:
import React from "react";import PropTypes from "prop-types";import { withRouter } from "react-router"; // A simple component that shows the pathname of the current locationclass ShowTheLocation extends React.Component { static propTypes = { match: PropTypes.object.isRequired, location: PropTypes.object.isRequired, history: PropTypes.object.isRequired }; render() { const { match, location, history } = this.props; return <div>You are now at {location.pathname}</div>; }} // Create a new component that is "connected" (to borrow redux// terminology) to the router.const ShowTheLocationWithRouter = withRouter(ShowTheLocation);
3.9 其他hooks
之前使用了useParams
和useRouteMatch
两个hook,还有另外两个hookuseHistory
和useLocation
useHistory
可以访问到history实例,我们可以通过这个实例访问某个路由
useLocation
返回location对象
到此这篇关于react-router-dom简介的文章就介绍到这了,更多相关react-router-dom内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!