# 一、React-router V4版本修改内容及一些坑
1、所有组件更改为从react-router-dom导入
//v2
import {Router,Route,hashHistory} from 'react-router';
// 4.xx写法
//v4
import {Route,BrowserRouter as Router, Switch} from 'react-router-dom';
// 如果搭配redux,你还需要使用react-router-redux
2、将所有
//v2
<Router history={hashHistory}>
<Route path="/" component={PCIndex}></Route>
<Route path="/details/:uniqueky" component={PCNewsDetails}></Route>
<Route path="/usercenter" component={PCUserCenter}></Route>
</Router>
现在需要更改为
BrowserRouter
- 这里的代码不仅仅是将
Router替换为BrowserRouter,而且还把所有的Route中用Switch包裹起来.
//v4
<BrowserRouter>
<Switch>
<Route exact path="/" component={MobileIndex}></Route>
<Route path="/details/:uniqueky" component={MobileNewsDetails}></Route>
<Route path="/usercenter" component={MobileUserCenter}></Route>
</Switch>
</BrowserRouter>
3、
<BroserRouter>只能有一个子节点,所以官网建议的是使用<Switch>进行包裹
// v3
<Route path='/' component={App}>
<IndexRoute component={Home} />
<Route path='about' component={About} />
<Route path='contact' component={Contact} />
</Route>
// v4
const App = () => (
<Switch>
<Route exact path='/' component={Home} />
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
</Switch>
)
4、最坑的地方:在当前目录下的文件路径不再使用./, 而是直接用/.
在进行文件引用的时候 ,
./src/js的写法需要更改文’/src/js’, 这是更改之后最坑的地方
# 二、安装
react-router-dom暴露出react-router中暴露的对象与方法,因此你只需要安装并引用react-router-dom即可
npm install --save react-router-dom
# 三、路由器(Router)
在你开始项目前,你需要决定你使用的路由器的类型。对于网页项目,存在
<BrowserRouter>与<HashRouter>两种组件。当存在服务器来管理动态请求时,需要使用<BrowserRouter>组件,而<HashRouter>被用于静态网站。通常,我们更倾向选择<BrowserRouter>,但如果你的网站仅用来呈现静态文件,那么<HashRouter>将会是一个好选择
# 四、历史(History)
每个路由器都会创建一个
history对象并用其保持追踪当前location[注1]并且在有变化时对网站进行重新渲染。这个history对象保证了React Router提供的其他组件的可用性,所以其他组件必须在router内部渲染。一个React Router组件如果向父级上追溯却找不到router组件,那么这个组件将无法正常工作
# 五、渲染
路由器组件无法接受两个及以上的子元素。基于这种限制的存在,创建一个
<App>组件来渲染应用其余部分是一个有效的方法
import { BrowserRouter } from 'react-router-dom'
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'))
# 六、<App>
应用通过
<App>组件定义。简化一下,我们将应用拆分成两个部分。<Header>组件包含网站的导航链接。<Main>组件则呈现其余内容
const App = () => (
<div>
<Header />
<Main />
</div>
)
# 七、路由(Route)
<Route>组件是React Router中主要的结构单元。在任意位置只要匹配了URL的路径名(pathname)你就可以创建<Route>元素进行渲染
1、路径(Path)
<Route>接受一个数为string类型的path,该值路由匹配的路径名的类型。例如:<Route path='/roster'/>会匹配以/roster开头的路径名。在当前path参数与当前location的路径相匹配时,路由就会开始渲染React元素。若不匹配,路由不会进行任何操作
<Route path='/roster'/>
// 当路径名为'/'时, path不匹配
// 当路径名为'/roster'或'/roster/2'时, path匹配
// 当你只想匹配'/roster'时,你需要使用"exact"参数
// 则路由仅匹配'/roster'而不会匹配'/roster/2'
<Route exact path='/roster'/>
- 注意:在匹配路由时,
React Router只关注location的路径名。当URL如下时
http://www.example.com/my-projects/one?extra=false
React Router去匹配的只是'/my-projects/one'这一部分
2、匹配路径
path-to-regexp包用来决定route元素的path参数与当前location是否匹配。它将路径字符串编译成正则表达式,并与当前location的路径名进行匹配比较
- 当路由地址匹配成功后,会创建一个含有以下属性的
match对象:url:与当前location路径名所匹配部分path:路由的地址isExact:path是否等于pathnameparams:从path-to-regexp获取的路径中取出的值都被包含在这个对象中
使用route tester这款工具来对路由与URL进行检验
3、创建你的路由
可以在路由器(router)组件中的任意位置创建多个
<Route>,但通常我们会把它们放在同一个位置。使用<Switch>组件来包裹一组<Route>。<Switch>会遍历自身的子元素(即路由)并对第一个匹配当前路径的元素进行渲染
- 我们希望匹配一下路径
/:主页/roster: 团体列表/roster/:number:运动员页面,使用运动员的编号作为标识/schedule:团队的赛程表
为了在应用中能匹配路径,在创建<Route>元素时必须带有需要匹配的path作为参数
<Switch>
<Route exact path='/' component={Home}/>
{/* both /roster and /roster/:number begin with /roster */}
<Route path='/roster' component={Roster}/>
<Route path='/schedule' component={Schedule}/>
</Switch>
4、<Route>是如何渲染的?
当一个路由的
path匹配成功后,路由用来确定渲染结果的参数有三种。只需要提供其中一个即可
component: 一个React组件。当带有component参数的route匹配成功后,route会返回一个新的元素,其为component参数所对应的React组件(使用React.createElement创建)。render: 一个返回React element的函数。当匹配成功后调用该函数。该过程与传入component参数类似,并且对于行级渲染与需要向元素传入额外参数的操作会更有用。children: 一个返回React element的函数。与上述两个参数不同,无论route是否匹配当前location,其都会被渲染
<Route path='/page' component={Page} />
const extraProps = { color: 'red' }
<Route path='/page' render={(props) => (
<Page {...props} data={extraProps}/>
)}/>
<Route path='/page' children={(props) => (
props.match
? <Page {...props}/>
: <EmptyPage {...props}/>
)}/>
通常
component参数与render参数被更经常地使用。children参数偶尔会被使用,它更常用在path无法匹配时呈现的’空’状态。在本例中并不会有额外的状态,所以我们将使用<Route>的component参数
- 通过
<Route>渲染的元素会被传入一些参数。分别是match对象,当前location对象以及history对象(由router创建)
5、<Main>
现在我们清楚了根路由的结构,我们需要实际渲染我们的路由。对于这个应用,我们将会在
<Main>组件中渲染<Switch>与<Route>,这一过程会将route匹配生成的HTML放在<main>节点中
import { Switch, Route } from 'react-router-dom'
const Main = () => (
<main>
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/roster' component={Roster}/>
<Route path='/schedule' component={Schedule}/>
</Switch>
</main>
)
- 注意:主页路由包含额外参数。该参数用来保证路由能准确匹配
path
6、嵌套路由
- 上面代码中有几个关键的点在 V4 中就不复存在了
- 集中式
router - 通过
<Route>嵌套,实现Layout和page嵌套 Layout和page组件 是作为router的一部分
- 集中式
-
V4中,我们不再使用{props.children}来嵌套组件了,替代的<Route>,当route匹配时,子组件会被渲染到<Route>书写的地方 -
基本使用

- 嵌套布局
方式一