安装
npm install 'react-router-dom'
示例
import React from 'react'
import {HashRouter,Route,Link} from 'react-router-dom'
const Basic = () => (
<HashRouter>//容器组件
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/page1">Page1</Link></li>
<li><Link to="/page2">Page2</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
</div>
</HashRouter>
)
容器组件
react-router的容器组件,就是最外层包括所有路由的组件,所有路由活动需要在容器组件中发生
容器组件主要包含BrowserRouter,HashRouter,MemoryRouter三个
- BrowserRouter: 浏览器自带的H5 API,restful风格,需要配合后台;
- HashRouter: 使用hash方式进行路由,路径后均有#;
- MemoryRouter: 在内存中管理history,地址栏不会变化。在reactNative中使用。
注意事项
- 所有与路由有关的组件(Link、NavLink、Route、Switch)必须包裹在容器组件中
- 容器组件有且只能有一个子元素
容器组件的使用
ReactDOM.render(<Provider store={store}>{/*这是react-redux的容器组件*/}
<HashRouter>{/*这是react-router-dom的容器组件*/}
<div>{/*一个子元素*/}
{/*Nav:header导航区域*/}
<Nav></Nav>
{/*基于 HashRouter展示不同的页面*/}
<Switch>{/*Switch就是在Switch的路由配置只能走一个*/}
<Route path='/' exact component={Home}></Route>
<Route path='/page1' component={Page1}></Route>
<Route path='/page2' component={Page2}></Route>
<Redirect to='/'></Redirect>{/*重定向到首页 */}
</Switch>
</div>
</HashRouter>
</Provider>, document.querySelector('#root'));
Route组件
Route组件用于组件的显示,Route组件上有path和component属性,对应的path会显示对应的component,路径和组件产生对应的映射关系(和vue-router的配置文件+router-view类似,但这是组件)。
<div>
<Route path='/' component={Home}></Route>
<Route path='/page1' component={Page1}></Route>
<Route path='/page2' component={Page2}></Route>
</div>
//以上代码,当浏览器访问/page1或者/page2路径,都会渲染Home组件,因为先和‘/’匹配了
细节知识点
- component属性:component能够接受一个组件名,也可以接受一个函数
<Route path="/" exact render={()=><h1>首页</h1>}/>
- 路由匹配的方式:要路径开头匹配成功既会显示对应的组件,就是当访问/page1路径的时候会匹配 / 的路径 ,解决办法是 exact属性
- exact:作用是严格匹配,路径是什么就匹配什么,避免路径匹配不正确的问题
<div> <Route path='/' exact component={Home}></Route> <Route path='/page1' component={Page1}></Route> </div> //此时访问'/page1',就不会再匹配‘/’了
Link组件和NavLink组件
Link组件
Link 组件是react-router中提供的路由切换的组件,基于它可以实现点击的时候实现路由的切换(相当于vue中的<vue-router>组件)
Link组件的属性
- to:'/xxx?xxx=123' 跳转到指定的路由地址
- to: {pathname:'/xxx',search:'xxx:123',state:''}//可以基于state的方式传参
- replace 默认值false 是替换HISTORY stack中当前的地址(true) 还是追加一个新的地址 (默认是追加)
- 基于link组件渲染,渲染后的结果是一个A标签,to对应的信息最后会变成href的内容
<Link to={{pathname:'/',search:'lx=logo'}} className="navbar">强国首页</Link>
NavLink组件
NavLink组件和LINK类似,不同在于,NavLink组件在当前页面地址和组件对应地址相吻合的时候,会默认给组件加一个active样式,让其有选中态(可以修改选中状态)
- activeClassName:把默认你加的active样式类改为自己设定的(默认是active)
- activeStyle:给匹配的NavLink设置行内样式
- exact 控制匹配的时候是否严格匹配(和route的一样)
- isActive:()=>{} 匹配成功后执行对应函数(相当于路由的钩子函数)
<NavLinkto={{pathname:'/',search:'lx=logo'}} className="navbar">强国首页</NavLink>
//匹配成功时,此元素会有active类名
//有时会有bug=>类名不切换,可以用hashChange事件监听或者使用withRouter
受路由控制组件
就是路由变化时,对应显示隐藏的那些组件
- 只有当前页面的 hash地址 和 路由指定的地址匹配,才会将对应的组件渲染(withRouter是没有地址匹配,都被模拟成受路由管控的)
class Nav extends React.Component{
render(){
return
<ul className="nav navbar-nav">
{/*NavLink不是点击谁,谁就有选中样式(但是可以路由切换),而是当前页面的哈希后的地址和NavLink中的to进行比较,哪个匹配了,哪个才有选中样式*/}
<li><NavLink exact to='/'>首页</NavLink></li>
<li><NavLink to='/page1'>page1</NavLink></li>
</ul>
}
}
export default withRouter(connect()(Nav))
//withRouter的意思是把一个非路由管控的组件,模拟成路由管控的组件
- 路由切换的原理 凡是匹配的路由,都会把对应的组件内容重新添加到页面中,相反,不匹配的都会在页面中移除掉,下次 重新匹配上,需要重新渲染到页面上,每一次路由切换(页面的哈希路由地址改变),都会从一级路由开始重新渲染
- 所有受路由管控的组件,在组件的 props上都添加了三个属性(相当于vue-route中的路由对象:包含当前路由的所有信息)
路由对象中的 history、location、 match、params
- history对象 (用于编程式导航)
let {history}=this.props;
history.go(n)//到任意有的记录中
history.push() //追加一条记录
history.replace()//不会追加记录
history.goback()//回退
history.goforward()//前进
- location
let {location:{pathname,search,state}}=this.props;
pathname当前的hash路由地址
search查询字符串
state 基于 redirect、link、nav-link中的to={},传递的是一个对象,对象中编写的state,就可以通过 loactuion.state获取
- match 匹配动态路由的值主要使用 params动态路由参数
let {match:{params}}=this.props;
console.log(params.id)
//获取的是动态路由匹配的一些结果,可用于动态传参
二级路由
<Switch>
{/*进入客户管理页面,我们默认为其展示的就是List区域内容,或者使用重定向也可以*/}
<Route path='/custom' exact component={List}></Route>
<Route path='/custom/list' component={List}></Route>
<Route path='/custom/create' component={Create}></Route>
<Route path='/custom/Detail/:id' component={Detail}></Route>
{/*进入客户管理页面,我们默认为其展示的就是List区域内容*/}
{/*<Redirect from='/custom' to='/custom/list'></Redirect>*/}
</Switch>
Switch组件,用于嵌套Route组件
- 和switch case一样,只能 选择一个,避免一个路径匹配多个组件
像这种情况,可能都会被渲染到页面上,此时Switch组件就有用了
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>{/*无论前边路由是否匹配成功,都会走这个*/}
路由数据传输方式
不推荐
- 本地存储 localstroage
- redux存储 (页面刷新数据就没了)
点击列表中某一项的时候,把信息存储到本地或者redux中,跳转到详情页面,把信息从本地或者redux中获取即可
推荐
- 1.问号传参
<Link to={{
pathname:'/home/user',
search:`?id=${item.id}`, //问号传参
}}>问号传参</Link>
受控组件中获取参数通过 this.props.location.search
- 2.state传值(一旦页面刷新state传的值就没了)
<Link to={{
pathname:'/home/user',
state:{'id':item.id},
}}>state传值</Link>
受控组件中获取参数通过 this.props.location.state
- 3.URL地址参数 path=‘/custom/detail/:id’
//动态路径设置
<Link to={{
pathname:`/home/user/${item.id}`
}}>URL地址参数</Link>
//Route路径配置
<Route path='/custom/Detail/:id' component={User}></Route>
//User组件内获取参数
this.props.match.params.id
路由重定向 Redirect
<Redirect from='/user' to='/user/list'></Redirect>
//from 从哪个路由 to定向到哪个路由
处理默认子路由
- Redirect
<Route path='/user/list' component={List}></Route>
<Redirect from='/user' to='/user/list'></Redirect>
//路径 /user下的默认显示的子路由是 /user/list ,/user和/user/list 最后渲染的都是List组件
- 两个路径都指向一个组件
<Route path='/user' exact component={List}></Route>
<Route path='/user/list' component={List}></Route>