1、路由方式
React-Router 中的 3 个核心角色:
- 路由器,比如 BrowserRouter 和 HashRouter
- 路由,比如 Route 和 Switch
- 导航,比如 Link、NavLink、Redirect
路由主要分为两种方式,一种是 history 模式,另一种是 Hash 模式;
- history 模式下:http://www.xxx.com/home import { BrowserRouter } from ‘react-router-dom’
- hash 模式下: http://www.xxx.com/#/home import { HashRouter } from ‘react-router-dom’
2、React-Router 基本构成
2.1 history,location,match
- history 对象:history对象保存改变路由方法 push ,replace,和监听路由方法 listen 等。
- location 对象:可以理解为当前状态下的路由信息,包括 pathname ,state 等。
- match 对象:这个用来证明当前路由的匹配信息的对象。存放当前路由path 等信息。
2.2 exact
Route 可以加上 exact ,来进行精确匹配,精确匹配原则,pathname 必须和 Route 的 path 完全匹配,才能展示该路由信息。
2.3 使用react-router-config
const RouteList = [
{
name: '首页',
path: '/router/home',
exact:true,
component:Home
},
{
name: '列表页',
path: '/router/list',
render:()=><List />
},
{
name: '详情页',
path: '/router/detail',
component:detail
},
{
name: '我的',
path:'/router/person',
component:personal
}
]
function Index(){
return <div>
<Meuns/>
{ renderRoutes(RouteList) }
</div>
}
2.4 Switch
Switch 作用是先通过匹配选出一个正确路由 Route 进行渲染。
<Switch>
<Route path='/home' component={Home} />
<Route path='/list' component={List} />
<Route path='/my' component={My} />
</Switch>
2.5 Redirect
Redirect 可以在路由不匹配情况下跳转指定某一路由。
<Switch>
<Route path='/router/home' component={Home} />
<Route path='/router/list' component={List} />
<Route path='/router/my' component={My} />
<Redirect from={'/router/*'} to={'/router/home' } />
</Switch>
3、路由使用方式
3.1 路由组件 props
被 Route 包裹的路由组件 props 中会默认混入 history 等信息;
class Home extends React.Component{
render(){
return <div>
<Children {...this.props} />
</div>
}
}
3.2 withRouter
对于距离路由组件比较远的深层次组件,通常可以用 react-router 提供的 withRouter 高阶组件方式获取 histroy ,loaction 等信息。
import { withRouter } from 'react-router-dom'
@withRouter
class Home extends React.Component{
componentDidMount(){
console.log(this.props.history)
}
render(){
return <div>
{ /* ....*/ }
</div>
}
}
3.3 useHistory 和 useLocation
对于函数组件,可以用 React-router 提供的自定义 hooks 中的 useHistory 获取 history 对象,用 useLocation 获取 location 对象。
import { useHistory ,useLocation } from 'react-router-dom'
function Home(){
const history = useHistory() /* 获取history信息 */
const useLocation = useLocation() /* 获取location信息 */
}
4、使用技巧
4.1 路由跳转
路由跳转有声明式路由和函数式路由两种。
- 声明式:
,利用 react-router-dom 里面的 Link 或者 NavLink 。 - 函数式:histor.push(‘/home’) 。
4.2 参数传递
url拼接
const name = 'alien'
const mes = 'let us learn React!'
history.push(`/home?name=${name}&mes=${mes}`)
state路由状态
const name = 'alien'
const mes = 'let us learn React!'
history.push({
pathname:'/home',
state:{
name,
mes
}
})
// 获取
const {state = {}} = this.prop.location
const { name , mes } = state
动态路径参数路由
// 参数做路径
<Route path="/post/:id" />
// 跳转
history.push('/post/'+id) // id为动态的文章id
5、路由拓展
5.1 嵌套路由
嵌套路由子路由一定要跟随父路由。比如父路由是 /home ,那么子路由的形式就是 /home/xxx ,否则路由页面将展示不出来。
/* 第二层嵌套路由 */
function Home(){
return <div>
<Route path='/home/test' component={Test} />
<Route path='/home/test1' component={Test1} />
</div>
}
/* 第一层父级路由 */
function Index(){
return <Switch>
<Route path="/home" component={Home} />
<Route path="/list" component={List} />
<Route path="/my" component={My} />
</Switch>
}
5.2 自定义路由
// 定义组件
function CustomRouter(props){
const permissionList = useContext(permissionContext) /* 获取权限列表 */
const haspermission = matchPermission(permissionList,props.path) /* 检查是否具有权限 */
return haspermission ? <Route {...props} /> : <Redirect to="/noPermission" />
}
// 使用
<CustomRouter path='/list' component={List} />
6、实践
第一步:根组件注入权限
function getRootPermission(){
return new Promise((resolve)=>{
resolve({
code:200, /* 数据模拟只有编写文档,和编写标签模块有权限,文档列表没有权限 */
data:[ '/config/index' , '/config/writeTag' ]
})
})
}
/* 路由根部组件 */
const Permission = React.createContext([])
export default function Index(){
const [ rootPermission , setRootPermission ] = React.useState([])
React.useEffect(()=>{
/* 获取权限列表 */
getRootPermission().then(res=>{
const { code , data } = res
code === 200 && setRootPermission(data)
})
},[])
return <Permission.Provider value={rootPermission} >
<RootRouter/>
</Permission.Provider>
}
第二部:编写权限路由
export function PermissionRouter(props){
const permissionList = useContext(Permission) /* 消费权限列表 */
const isMatch = permissionList.indexOf(props.path) >= 0 /* 判断当前页面是否有权限 */
return isMatch ? <Route {...props} /> : <Redirect to={'/config/NoPermission'} />
}
第三部:注册权限路由和无权限跳转页面
<Switch>
<PermissionRouter path={'/config/index'} component={WriteDoc} />
<PermissionRouter path={'/config/docList'} component={DocList} />
<PermissionRouter path={'/config/writeTag'} component={WriteTag} />
<PermissionRouter path={'/config/tagList'} component={TagList} />
<Route path={'/config/NoPermission'} component={NoPermission} />
</Switch>