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'@withRouterclass 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.locationconst { 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 } = rescode === 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>
