要想真正掌握 React 是很困难的,要学习的东西太多了.react 提供 react-router进行路由的跳转和路由的管理
本篇文章使用的 demo 放在GitHub 上
react-router 4.0 之前提出 react-router-dom ,其相较于 4.0之前的 react-router ,可以理解为新增了操作 dom 的 API,react-router 4.0 后我们只需要引入 react-router-dom 即可
安装:cnpm i react-router-dom --save
组件 | 功能 | 属性 |
---|---|---|
Link | 提供路由跳转,Router中的超链接 | to |
BrowserRouter | 整体容器,提供路由封装(使用context实现路由跳转中参数的传递等) | |
Route | 接受路由,指定渲染组件和渲染方式,配合Link使用 | component/path/exact/render |
Switch | 路由切换组件 | |
Redirect | 路由重定向组件 | from/to |
Router 即 BrowserRouter ,4.0 之前使用 Router ,用于包裹路由,提供路由封装容器,在路由跳转中起到传递各种参数的作用.使用 context 实现.
Link 组件类似超链接,Route 标签搭配 Link 完成链接
假设页面有一个首页(home)和一个博客页(blog),首先使用Link
组件创建两个链接标签 to
属性指定跳转路由
import {Link,BrowserRouter,Switch,Route} from 'react-router-dom'
function App() {
return (
<BrowserRouter>
<Link to='/home'>首页</Link>
<br/>
<Link to='/blog'>博客</Link>
</BrowserRouter>
);
}
export default App;
现在点击两个链接(Link) 是没有效果,因为没有指定相应路由渲染的组件,这个时候就需要Route组件的作用了
Route 组件有 component 和 render 两个属性指定渲染样式,component 是指定路由跳转渲染组件,render 是利用函数和 jsx 的形式指定样式,两个选其一即可.path 属性指定对应于 Link 的 to。
class Home extends Component{
render(){
return(
<h2>这是首页</h2>
)
}
}
function App() {
return (
<BrowserRouter>
<Link to='/home'>首页</Link>
<br/>
<Link to='/blog'>博客</Link>
<Route path='/home' component={Home}></Route>
<Route path='/blog' render={()=><h2>这是博客页</h2>}></Route>
</BrowserRouter>
);
}
现在点击首页或者博客就会渲染相应的 component 指定组件或者渲染内容(render)。路由也进行了相应的跳转
Route 组件还有一个属性为 exact ,代表是否严格匹配,默认值为 false 不严格匹配
path | 实际路径 | exact | 是否匹配 |
---|---|---|---|
/a | /a/b | false | 是 |
/a | /a/b | true | 否 |
上边表格表示 exact 是否指定的作用,可以看出如果不指定 exact 严格匹配的话当路径为 /a/b
时是会匹配到 /a
路由的
在示例中我们将 首页路由改为 /
,如果不为其添加 exact 属性,当我们店家 博客页 时渲染如下:
可以看到路由为/blog
时同样匹配到了 路由/
,为路由 /
所在Route
组件指定 exact 属性就可以解决此问题。
Switch 组件的作用非常简单,主要用于处理 404 页面的请求,或者说处理没有匹配到 Route 组件的请求,实现方式使用 Switch 组件包裹 所有的 Route 组件,其中一个 Route 组件不指定 path 属性,当未成功匹配路由时则跳转该页面
class Home extends Component{
render(){
return(
<h2>这是首页</h2>
)
}
}
function App() {
return (
<BrowserRouter>
<Link to='/'>首页</Link>
<br/>
<Link to='/blog'>博客</Link>
<br/>
<Link to='/to404'>to404</Link>
<Switch>
<Route path='/' exact component={Home}></Route>
<Route path='/blog' render={()=><h2>这是博客页</h2>}></Route>
<Route render={()=><h2>进入404了</h2>}></Route>
</Switch>
</BrowserRouter>
);
}
Redirect 用于前端重定向的功能,有两个属性 from
和 to
指定点击路由和需要跳转的路由,下边示例实现点击 blog 页时跳转到新的一个页面
function App() {
return (
<BrowserRouter>
<Link to='/'>首页</Link>
<br/>
<Link to='/blog'>博客</Link>
<br/>
<Link to='/to404'>to404</Link>
<Switch>
<Route path='/' exact component={Home}></Route>
{/* 这是博客页
}> */}
<Redirect from='/blog' to='/new'></Redirect>
<Route path='/new' render={()=><h2>这是新的页面</h2>}></Route>
<Route render={()=><h2>进入404了</h2>}></Route>
</Switch>
</BrowserRouter>
);
}
当点击博客链接时就会跳转到 /new 路由
Prompt 组件用于确认是否跳转,有两个属性
class Blog extends Component{
render(){
return(
<form>
<Prompt when={true} message={'是否确定要离开!'}></Prompt>
<input type="text"/>
</form>
)
}
}
function App() {
return (
<BrowserRouter>
<Link to='/'>首页</Link>
<br/>
<Link to='/blog'>博客</Link>
<Switch>
<Route path='/' exact render={()=><h2>这是首页</h2>}></Route>
<Route path='/blog' component={Blog}></Route>
</Switch>
</BrowserRouter>
);
}
当点击博客页后离开,会弹出如下
现假设我们有三篇文章在博客页下
class Blog extends Component{
render(){
return(
<div>
<ul>
<li><Link to='/detail/1'>这是第一篇文章</Link></li>
<li><Link to='/detail/2'>这是第二篇文章</Link></li>
<li><Link to='/detail/3'>这是第三篇文章</Link></li>
</ul>
</div>
)
}
}
三篇文章的显示页样式都相同,只是数据不同,这种情况下我们应该怎么做呢?
Route 组件为我们提供了匹配方法
<Route path='/detail/:id'></Route>
上面例子的 path 参数代表携带的参数名为 id ,可以匹配 /detail/* ,接受参数为 id=*
function Detail(){
return(
<div>这是文章详情页</div>
)
}
class Blog extends Component{
render(){
return(
<div>
<BrowserRouter>
<ul>
<li><Link to='/detail/1'>这是第一篇文章</Link></li>
<li><Link to='/detail/2'>这是第二篇文章</Link></li>
<li><Link to='/detail/3'>这是第三篇文章</Link></li>
</ul>
<Route path='/detail/:id' component={Detail}></Route>
</BrowserRouter>
</div>
)
}
}
这样就可点击文章都会跳转到对应的路由显示文章详情页
需要注意的是携带参数的 Route 需要注意 exact 的问题,参照自己的情况是否设置
多参数问题同上 ,例如路由 /a/b/c ,Route 组件可设置 path 属性 /a/:id/:obj 进行匹配,假如路由 /a/b/c/d 匹配该Route组件是不能获取到 d 参数的,因为 Route 组件的 path 属性没有指定 d 参数的位置
那么现在的问题是 Detail 组件怎么获取路由参数的呢?
接受参数有两种情况:
function Detail(props){
// console.log(props)
return(
<div>这是第{props.match.params.id}篇文章详情页</div>
)
}
如果我们打印 props 可以看到传递了很多的参数,这些参数就是路由参数就是需要讲解的
match、history、location 三个就是我们上边的例子获取到的参数里边的内容
参数说明:
参数名称 | 说明 |
---|---|
match | 携带匹配结果及url参数 |
history | 携带历史纪录操作的封装 |
location | 携带url解析结果(类似与node种的url.parse()) |
match和history 都比较简单,打印以下其实也能大概知道他的作用
history
history 主要用于保存实现页面的跳转历史纪录,用于实现前进后退非常有用
history 实现历史纪录主要使用栈结构保存(先进后出,后进先出),history 属性说明:
属性 | 说明 |
---|---|
length | 栈的长度 |
action | 当前栈动作(PUSH|REPLACE|POP) |
方法 | 说明 |
push | 新纪录入栈 |
replace | 替换当前记录 |
go(n) | 在栈中将指针移动到第n个位置 |
goBack() | 等价go(-1) |
goForward() | 等价于go(1) |
block() | 阻止路由跳转,类似于prompt |
push 方法传入 path ,类似与Link 跳转,将新页面推入栈中并进行跳转
replace 方法传入 path ,删掉当前记录替换为新的记录,而不是叠加在当前记录上
goForward 向前走
goBack 向后跳转
现在利用 history 为页面添加点击博客详情页后添加一个返回上一级的功能
function Detail(props){
// console.log(props)
return(
<div>
<div>这是第{props.match.params.id}篇文章详情页</div>
<button onClick={props.history.goBack}>返回上一级</button>
</div>
)
}
以上就是 react-router 的简单使用,要想掌握好他还是要孰能生巧