做为 React
全家桶的一员,若是咱们想要开发一个 React
应用,那么 react-router
基本上是咱们绕不过去的基础。基于此,对它的了解和使用也是必不可少的一步html
本文将重点介绍实际应用中经常使用的一些 API
以及实践过程当中遇到的一些问题,目标很简单:会用前端
基于react-router
v5.0.1
,WEB
应用程序
国际惯例,首先咱们须要安装vue
npm install --save react-router-dom
从这一步开始,已经有同窗有疑问了:咱们明明在说 react-router
怎么要下载安装 react-router-dom
呢react
React Router
如今已经被划分红了三个包:react-router
,react-router-dom
,react-router-native
git
react-router
为React Router
应用提供了核心的路由组件和函数,另外两个包提供了特定环境的组件(浏览器和react-native
对应的平台),不过他们也是将react-router
导出的模块再次导出
由于咱们须要开发一个 web
应用,因此直接安装 react-router-dom
就能够了github
首先,让咱们经过一个小小的示例来感知一下 react-router
web
import React from 'react' import ReactDom from 'react-dom' import { BrowserRouter, Route, Link, Switch } from 'react-router-dom' const Index = () => <div>Index页面</div> const About = () => <div>About页面</div> const App = () => { return ( <BrowserRouter> <div> <div> <ul> <li><Link to='/'>Index</Link></li> <li><Link to='/about'>About</Link></li> </ul> </div> <div> <Switch> <Route path='/' exact component={Index}></Route> <Route path='/about' exact component={About}></Route> </Switch> </div> </div> </BrowserRouter> ) } ReactDom.render(<App />, document.getElementById('app'))
经过上面的代码咱们已经实现了路由的基本功能,匹配不一样的路径,渲染不一样的组件。下面,咱们就上面的示例,认识一些 react-router
中高频率出现的概念vue-router
React Router
应用程序的核心,每一个 router
都会建立一个 history
对象,用来保持对当前位置的追踪npm
在 web
项目中,react-router-dom
提供了 BrowserRouter
和 HashRouter
路由。这两个路由都会为你建立一个专门的 history
对象。至于使用场景,通常状况下若是咱们使用的是一个非静态的站点、要处理不一样的 url
就使用 BrowserRouter
,相反若是只处理静态的 url
,则使用 HashRouter
编程
Route
组件的主要职责:当连接符合匹配规则时,渲染组件
路由匹配是经过比较 Route
的 path
属性和当前地址的 pathname
来实现的。当一个 Route
匹配成功时,它将渲染其内容,当它不匹配时就会渲染 null
。没有路径的 Route
将始终被匹配
Route
组件经常使用属性:
path
: 字符串类型,用来匹配 ulr
exact
: boolean
类型,若是为 true
,则只有在路径彻底匹配 location.pathname
时才匹配component
: 只有当位置匹配时才会渲染的 React
组件注意点:
Route
组件属性都不是必须的,若是缺乏path
属性,那么将会匹配到任意url
<Route path='/' exact component={Index} /> <Route component={About} />
使用render
或者children
属性能够替代component
属性,因为render
与children
都是函数的形式,因此能够在它们当中作一些比较复杂的逻辑
render
函数也是在匹配url
的时候渲染,而children
函数 任什么时候候 都渲染,当路由匹配的时候match
是一个对象,不然为null
当三者一块儿使用的时候,优先级为
children
>component
>render
<!-- 使用 render 属性 --> <Route path='/about' render={() => <div>这个是render渲染的about页面</div>} /> <Route path='/about' render={(props) => <About {...props} />} /> <!-- 使用 children 属性 --> <Route path='/about' children={() => <div>这是一个children渲染的about页面</div>} <Route path='/about' children={({match}) => match ? <div>1</div> : <div>2</div> }
渲染与该地址匹配的第一个子节点Route
或者Redirect
这个组件最重要的做用是能够将 Route
组件分组
<Switch> <Route path='/user' render={()=><div>user页面</div>} /> <Route path='/:id' render={()=><div>子成员</div>} /> <Route render={()=><div>about页面</div>} /> </Switch>
在上面这个示例中,在没有 Switch
组件包裹的状况下,若是 ulr
是 /user
,那么三个页面将会所有匹配到。这样的设计在必定程度上给咱们提供了便利,好比说一个公共页面须要渲染好几个组件的状况。可是有时候咱们并不想访问到所有的匹配组件,这个时候就能够将这些 Route
组件使用 Switch
包裹起来,它将永远渲染符合匹配项的第一个组件
注意点:
Switch
匹配的规则是同一个组中渲染第一个匹配组件,也就是说若是是包裹在两个不一样的 Switch
组件中的,会分别渲染匹配到的第一个组件Switch
组件中不能嵌套内置标签元素,好比 div
span
,可是能够嵌套组件,甚至能够添加 path
属性进行匹配, 实际上 Route
自己就是组件,可是建议仍是只嵌套 Route
或者 Redirect
组件相信小伙伴们看过前面的示例以后,应该对 Link
不会陌生了。它的做用就是提供声明式的可访问导航
Link
经常使用属性:
to
:能够是 String
类型或者具备 pathname
、search
、hash
、state
任何属性的对象pathname
: 表示要连接到的路径的字符串
search
: 表示查询参数的字符串形式
hash
: 放入网址的 hash
state
: 状态持续到 location
replace
:boolean
类型,若是为 true
,点击连接将替换当前历史记录NavLink
一个特殊版本的Link
,当它与当前URL
匹配时,为其渲染元素添加样式属性,其用法与Link
基本相同
注意点:
activeClassName
或者 activeStyle
属性进行添加,简单来讲就是使用 class
类或者行内样式NavLink
有一个 exact
属性,若是为 true
,则仅在位置彻底匹配时才应用 active
的类/样式顾名思义,重定向组件,组件中的 to
属性是必须的
属性:
to
:string
类型或者一个对象(pathname
属性是重定向到的 URL
)push
:boolean
类型,当 true
时,重定向会将新地址推入 history
中,而不是替换当前地址,就是经过 history.push
或者 history.replace
实现from
:重定向 from
的路径名,简单说就是将要进入的 url
exact
:彻底匹配 from
;至关于 Route.exact
这个组件在一些场景中有很好的效果,好比咱们登陆场景,前面咱们介绍过的 Route
组件渲染属性使用 render
或者 children
的时候,就彻底能够根据判断条件执行不一样的路由跳转
<!-- 官网示例代码 --> <Route exact path='/' render={()=>( loggedIn ? ( <Redirect to="/dashboard"/> ) : ( <PublicHomePage/> ) )} /> <!--或者--> <Route path='/about' children={({match})=>( match ? ( <About /> ) : ( <User /> ) )} />
前面介绍 Switch
组件时,有过它的身影,实际上它能够和 Switch
组件很好的配合,好比:
<Switch> <Redirect from='/user' to='/about' /> <Route path='/user' render={()=><div>User页面</div>} /> </Switch>
须要注意的地方:
from
属性只能用于在 Redirect
内部渲染 Switch
时匹配地址Redirect
组件中 from
匹配的 Route
要在前面定义<!--错误姿式,这样是没有效果的--> <Route path='/user' render={()=><div>User页面</div>} /> <Redirect from='/user' to='/about' />
默认状况下,通过路由匹配的组件才拥有路由参数,咱们就能够在其中使用 编程式导航,好比:
this.props.history.push('/about')
然而,不是全部的组件都是与路由相连的,好比直接在浏览器输入地址打开的。这个时候咱们访问组件 props
的时候,它是一个空对象,就没办法访问 props
中的 history
、match
、location
等对象
因此 这个时候 withRouter
闪亮登场
withRouter
的用法很简单:
import React, { Component } from 'react'; <!--引入--> import { Route, Link, Switch, withRouter } from 'react-router-dom' class App extends Component { render() { <!-- 没有使用 withRouter 的时候,是一个空对象--> console.log(this.props) return ( <div> <Link to='/'>Index</Link> <Link to='/about'>About</Link> <Switch> <Route path='/' exact render={()=> <div>Index页面</div>} /> <Route path='/about' render={()=> <div>About页面</div>} /> </Switch> </div> ); } } <!--执行--> export default withRouter(App)
固然,还有不少种使用方式,好比经过 withRouter
监听 loaction
对象改变文档标题或者配合 redux
使用等等
详见 示例demo
了解了 react-router
的这些基本知识点,貌似咱们已经能够写出来一个用路由搭建的项目了。可是,请暂时停下脚步想一下:在一个项目当中,若是咱们遇到嵌套的路由呢、动态参数的路由呢?固然,只用前面了解到的东西,彻底能够写出来,但那是在是太 low
了
在解答前面的两个问题以前,咱们须要先了解一个 match
对象
相信在前面的 withRouter
模块,小伙伴们已经知道了 match
对象的存在,在动态路由和路由嵌套时,咱们会常常和它打交道
一个match
对象中包涵了有关如何匹配URL
的信息
它包含如下属性:
params
:与动态路径的 URL
对应解析,它里面包含了动态路由里面的信息path
:用于匹配的路径模式url
:用于匹配部分的 URL
isExact
- 若是为 true
匹配整个 URL
(没有结尾字符)注意点:
Route
没有 path
,那么将会一直与他最近的父级匹配。这也一样适用于 withRouter
match
对象中的 url
和 path
,简单来讲 path
是匹配的规则, url
则是实际匹配到的路径了解了 match 对象,动态路由的定义其实很简单
<Link to='/video/1'>视频教程1</Link> <Link to='/video/2'>视频教程2</Link> <Route path='/video/:id' component={Video} />
Route
组件能够匹配到 Link
连接跳转的路径,而后再 match
对象的 params
属性中就能够拿到动态数据的具体信息
React Router 4
再也不提倡中心化路由,取之的是路由存在于布局和 UI
之间,Route
自己就是一个组件
实现路由嵌套最简单的方式:
<!--父组件--> <Route path='/workplace' component={Workplace} /> <!--子组件--> <Route path='/workplace/money' component={Money} />
固然,使用 match
来进行匹配会更加优雅
<!--父组件--> <Route path='/video' component={Video} /> <!--子组件--> <Route path={`${this.props.match.url}/react`} component={ReactVideo} />
注意点:
exact
使用这样的方式来配置路由规则,咱们就只须要考虑 component
的渲染时机就能够了。可是,一样的也会给咱们带来一些问题,好比说路由规则不是很直观,尤为是对于写过 vue
的小伙伴来讲,要是有一个像配置 vue-router
规则的东西就行了。这个时候,咱们能够试着去了解一个这个东西了 react-router-config
详见 示例demo
突如其来的结束语
关于 react-router
的基本用法就是想上面介绍的那样,可是想要探究更多有意思或者更优雅的用法,还须要咱们在具体的项目中去磨练,好比说路由的拆分、按需加载等等一系列东西
若是你也对 React
中的其余内容感兴趣,想要了解更多前端片断,能够 点击这里 ,欢迎 star
关注