对于以前没有接触过 React Router 的同窗来讲,必定要注意:最新的React Router版本是 V5 。除此以外,还有 V2 V3 V4 版本。其中V4和V5版本的用法和理念基本上是一致的,可是和以前的V二、V3版本有较大差别。css
因此在学习以前必定要弄清楚本身使用的是哪个版本,若是是V4或者V5,V4和V5两个版本的文档笔记均可以参考;若是你用的是V2或者V3,那么必定要找到对应的文档笔记。react
在我学习React Router的时候,使用的是V5,因此这篇笔记也是对 React Router V5 的一些总结。若是你是一名React小白,我想经过这篇笔记,你能够基本会使用React Router。若是你想更深层次地理解React Router,能够访问:reacttraining.com/react-route… 。webpack
在V4和V5版本中,React Router分红了两个大的方向:React Web Router 和 React Native Router 。若是你是建立的React Web应用,就使用React Web Router ,这里咱们使用的就是这个Router,因此执行如下命令进行安装:web
npm install --save react-router-dom
复制代码
想要在React项目中使用路由,必不可少的有两个组件(component): BrowserRouter 和 Route 。在React项目中,经过如下命令引入这两个组件:shell
import { BrowserRouter, Route } from "react-router-dom";
复制代码
BrowserRouter 组件是React Router的核心,Route组件是React Router的具体配置。举个例子来讲:BrowserRouter 组件就像是一个文具盒,Route组件就像是一件件文具同样,须要放在这个盒子里。这样咱们在使用文具的时候,只须要打开文具盒,从里面取出便可。npm
了解了这层关系,咱们就能够在React中配置路由了,配置很是简单,示例代码以下:浏览器
// React 应用中的 App.js 文件
import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom'
import Set from './views/set/Set'
import Help from './views/help/Help'
class App extends React.Component {
render() {
return (
<BrowserRouter>
<Route path="/help" component={Help} />
<Route path="/set" component={Set} />
</BrowserRouter>
);
}
}
export default App;
复制代码
在App.js文件中配置完车以后,而后在React入口文件中(通常是index.js文件),引入App.js文件并挂载到页面上,示例代码以下:服务器
// React 应用中的入口文件 index.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
render((
<App /> ), document.getElementById('root')) 复制代码
挂载完成以后,经过npm run start
等命令启动本地开发服务器,就能够经过路由访问咱们的React项目了。实例以下:react-router
简单介绍一下以上代码中的路由配置规则,以这条路由配置为例:dom
<Route path="/help" component={Help} />
复制代码
Help 是咱们以前定义好的一个React组件,该组件的定义代码以下:
import React, { Component } from 'react'
class Help extends Component {
render() {
return (
<div className="help-box"> 帮助与反馈 - 页面 </div>
);
}
}
export default Help;
复制代码
当咱们在浏览器地址栏中输入 http://localhost:3000/help
的时候,React Router 会匹配到 <Route path="/help" component={Help} />
这一条记录,而后就会在当前位置渲染对应的component。
注意是当前位置,说得更通俗一点:就是使用将Help组件中的代码替换掉 <Route path="/help" component={Help} />
代码,进而渲染出路由对应的component。关于这一点,后面会有更详细的解释。
经过上面的配置,咱们已经能够经过输入URL来跳转路由,可是更多状况下,咱们但愿能够经过点击页面上的连接进行路由的跳转,好比如下的示例:
想要实现这一点,咱们只须要引入 Link 这个组件便可,具体代码以下:
// React 应用中的 App.js 文件
import React from 'react';
import { BrowserRouter, Route, Link } from 'react-router-dom' // 引入 Link 组件
import Set from './views/set/Set'
import Help from './views/help/Help'
class App extends React.Component {
render() {
return (
<BrowserRouter>
{/* 注意 Link 组件必定要位于 BrowserRouter 组件中 */}
<ul>
<li><Link to="/help">Help</Link></li>
<li><Link to="/set">Set</Link></li>
</ul>
<Route path="/help" component={Help} />
<Route path="/set" component={Set} />
</BrowserRouter>
);
}
}
export default App;
复制代码
如今咱们已经掌握了React Router的基本使用,可是这个时候咱们掌握的知识还不足以让咱们熟练地使用它,因此下面为你们介绍React Router更多内容。
在对Route进行配置的时候,咱们能够传如下参数:path、exact、component、render、children 。这些参数都不是必须的,也就是说,咱们有不少中配置Route的方式,常见的有如下几种:
<BrowserRouter>
<Route component={Wallet} />
<Route path="/" component={Index} />
<Route exact path="/" component={Index} />
<Route path="/help" component={Help} />
<Route path="/render" render={ () => { return <h1>我是匹配到的路由</h1> } } />
</BrowserRouter>
复制代码
这里分别介绍以上五种Route的配置方式:
<Route component={Wallet} />
在配置Route的时候没有指定 path 属性,这时只要你打开项目,不管你访问什么路径,这个Route都会匹配到。
<Route path="/" component={Index} />
配置Route的时候,指定 path="/"
,和上面配置的效果同样,只要你打开项目,不管你访问什么路径,这个Route都会匹配到。这种配置方式咱们成为 "非严格匹配" ,你在项目中访问的任何一个路径,里面都会包含path="/"
的路径。因此不管访问什么路径,这个Route都会匹配到。
<Route exact path="/" component={Index} />
和上面一条的配置方式不一样,这里在配置Route的时候,传入了 exact 属性,说明这个配置方式是 "严格匹配" ,只有当咱们访问项目的根路径的时候,才会匹配到这个Route。好比:localhost:3000/ 。
<Route path="/help" component={Help} />
一条很常规的Route配置方式,当咱们访问"/help"路径的时候,匹配到这个Route,进而渲染出对应的component。
<Route path="/render" render={ () => { return <h1>我是匹配到的路由</h1> } } />
和上一条路由配置不一样的是,这里没有component属性,而是换成了render属性。该属性是一个函数,当匹配到这个Route的时候,页面将会渲染出这个函数返回的内容。
Switch组件的使用其实很是简单,举个例子:若是说BrowserRouter组件是一个大的文具盒的话,那么Switch组件就是这个大文具盒中的一个小袋子,Route组件就是这个小袋子中的一支铅笔,咱们须要铅笔的时候,直接从这个小袋子里面取出一支便可。注意:是最多只能取出一支铅笔。
也就是说,当进行路由匹配的时候,一旦匹配到了Switch组件中的一个Route,那么就不会再继续匹配。好比如下实例:
<BrowserRouter>
<Switch>
<Route component={Wallet} />
<Route path="/" component={Index} />
<Route path="/help" component={Help} />
<Route path="/render" render={() => { return <h1>我是匹配到的路由</h1> }} />
</Switch>
</BrowserRouter>
复制代码
若是咱们访问 "localhost:3000/help" 路径,虽然前三个Route都匹配,可是页面只会渲染第一个匹配到的Route,其余的都被忽略。看到这里你可能会问,这个组件有什么做用呢?能够在如下场景中发挥做用:若是当前路径没有匹配到任何Route的时候,路由跳转到 404 页面,那么就能够这样写:
<BrowserRouter>
<Switch>
<Route path="/set" component={Set} />
<Route path="/help" component={Help} />
<Route path="/render" render={() => { return <h1>我是匹配到的路由</h1> }} />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
复制代码
经过上面的配置,若是当前路径有匹配到最后一个以外的Route,那么就显示对应内容,再也不继续匹配;若是没有匹配到最后一个以外的Route,就显示最后一个Route,由于这个Route能够匹配任何路径。能够把这个Route对应到 404 页面。
前面讲述了Route的配置和匹配规则,下面咱们讲述一下,当路径匹配到Route以后,会如何渲染对应的内容。
以前有提到过:是在 当前位置 渲染内容,对于一些刚入门的小白来讲,可能不能马上理解当前位置是什么位置。因此咱们举个例子,好比咱们在项目的App.js组件中有如下配置代码:
class App extends React.Component {
render() {
return (
<div className="content">
<BrowserRouter>
<Route exact path="/" component={Index} /> {/* 位置 A */}
<Route path="/help" component={Help} /> {/* 位置 B */}
<Route path="/set" component={Set} /> {/* 位置 C */}
</BrowserRouter>
</div>
);
}
}
复制代码
那么当路径为 "help" 的时候,就会匹配到第二个Route,那么React Router就会在 位置B 对应的这一行将 Route 组件替换成Help组件;而其余没有匹配到的Route,会被替换成null,至关于将这些 Route 组件直接删去。最终的结果如如下代码所示:
// Help 组件的定义代码能够在上文中找到
class App extends React.Component {
render() {
return (
<div className="content"> <div className="help-box"> 帮助与反馈 - 页面 </div> </div>
);
}
}
复制代码
之因此讲这么一个知识点,是为后面介绍如何配置嵌套路由作准备,这里能够先提一下:若是咱们想在 组件A中 嵌套几个子路由,那么就能够将这几个Route配置,写到组件A中,一旦路径匹配到了这些Route,就会在组件A中对应的位置渲染子路由对应的组件。听不懂不要紧,后面会有详细的解释。
经过上面的笔记,你可能会认为:Route组件必须位于BrowserRouter组件中,且两个组件必须在同一个文件中。
其实否则,从代码结构上说,Route组件确实必须位于BrowserRouter组件中,可是两个组件不必定非要在一个文件中,只要打包编译以后,两个组件知足Route组件位于BrowserRouter组件中就能够。好比如下的写法也是彻底正确的:
// 项目的入口文件 index.js
import React from 'react'
import { render } from 'react-dom'
import App from './App'
import { BrowserRouter } from 'react-router-dom'
render((
<BrowserRouter> <App /> </BrowserRouter>
), document.getElementById('root'))
复制代码
// App.js 文件
import React from 'react';
import { Route, NavLink } from 'react-router-dom'
import Set from './views/set/Set'
import Help from './views/help/Help'
import Index from './views/index/Index'
import Wallet from './views/wallet/Wallet'
class App extends React.Component {
render() {
return (
{/* 注意这里已经没有了 BrowserRouter 组件 */}
<div className="content">
<ul>
<NavLink activeClassName="selected" to="help">help</NavLink >
<NavLink activeClassName="selected" to="index">index</NavLink >
<NavLink activeClassName="selected" to="wallet">wallet</NavLink >
<NavLink activeClassName="selected" to="set">set</NavLink >
</ul>
<Route path="/help" component={Help} />
<Route path="/index" component={Index} />
<Route path="/wallet" component={Wallet} />
<Route path="/set" component={Set} />
</div>
);
}
}
export default App;
复制代码
嵌套路由,顾名思义就是在一个主路由匹配到的页面中再配置一些路由,咱们如今就来说述如下如何使用 React Router 配置嵌套路由,配置完成以后,咱们会看到如下效果:
在以前的基础之上,咱们已经配置好了一级路由,便可以通关点击 set 按钮跳转到匹配到的Route对应的组件中,即Set组件,具体配置能够参考上一个代码块中的代码。
下面咱们要作的就是在Set组件中,进行配置二级路由,即嵌套路由。配置很是简单,这里先直接给出代码:
import React, { Component } from 'react'
import { Route, Link } from 'react-router-dom'
import SetSystem from '../SetSystem'
import SetPerson from '../SetPerson'
import SetTime from '../SetTime'
import './Set.scss'
class Set extends Component {
componentDidMount() {
// 当前页面匹配到的路径,这里是"/set"
// 使用这个路径,配置Route和Link
console.log(this.props.match.path);
}
render() {
return (
<div className="set-box">
我的设置 - 页面
<div className="link-list">
<Link to={`${this.props.match.path}/system`}>system</Link>
<Link to={`${this.props.match.path}/person`}>person</Link>
<Link to={`${this.props.match.path}/time`}>time</Link>
</div>
<div className="child-router">
<Route path={`${this.props.match.path}/system`} component={SetSystem} />
<Route path={`${this.props.match.path}/person`} component={SetPerson} />
<Route path={`${this.props.match.path}/time`} component={SetTime} />
</div>
</div>
);
}
}
export default Set;
复制代码
注意代码中咱们引入了 Set.scss 样式文件,给页面元素添加一些很是简单的样式,具体样式你能够自定义,这里的示例代码以下:
.set-box {
.link-list {
a {
margin: 0px 10px;
}
}
}
复制代码
代码书写完成以后,咱们就配置好了嵌套路由,启动项目你就能够看到上面GIF中展现的效果。这里对上面的配置作简单的解释:
首先再提一下:匹配到的Route会在 当前位置 渲染匹配到的内容(这个内容多是component组件,render函数返回的结果等)。
就是由于React Router的这个特性,咱们才能配置嵌套路由,不然,及时匹配到了Route,可是咱们不知道它的渲染位置,也不能实现此功能。
其次再说一下 this.props.match
这个属性,经过这个属性,咱们能够得到当前页面,即一级路由匹配到的组件对应的路径,在这里 this.props.match
的值是 "/set"。
了解了这一点,咱们就能够在 this.props.match
的帮助下,设置二级路由的路径。因此如下两种写法是等价的,可是第一种写法更加灵活:
{/* 第一种写法 */}
<Link to={`${this.props.match.path}/system`}>system</Link>
<Route path={`${this.props.match.path}/system`} component={SetSystem} />
{/* 第二种写法 */}
<Link to="/set/system">system</Link>
<Route path="/set/system" component={SetSystem} />
复制代码
最后再再说一下 Route组件 和 BrowserRouter组件 的位置问题。初次接触React Router的小白可能会问:在设置嵌套路由的时候,Route组件怎么没有包含在BrowserRouter组件中?
事实上,在使用webpack将代码打包打包编译以后,Route组件已经包含在BrowserRouter组件中了。在代码层面咱们能够这样理解:Route组件包含于Set组件中,Set组件包含于App组件中,App组件包含在BrowserRouter中。因此Route组件已经包含在BrowserRouter组件中。
啰啰嗦嗦写完了对React Router的总结,内容挺多可是都很基础,但愿能够帮到刚刚入门的小白。
若是大神们看到错误之处,还但愿各位能及时指正。