React-Router是React生态外面很重要的一环,当初React的单页利用的路由根本都是前端本人治理的,而不像以前是后端路由,React治理路由的库罕用的就是React-Router。本文想写一下React-Router的应用,然而光介绍API又太平淡了,而且官网文档曾经写得很好了,我这里就用一个常见的开发场景来看看React-Router是怎么用的吧。咱们个别的零碎都会有用户拜访权限的限度,某些页面可能须要用户具备肯定的权限能力拜访。本文就是用React-Router来实现一个前端鉴权模型。

本文全副代码曾经上传GitHub,大家能够拿下来玩玩:https://github.com/dennis-jiang/Front-End-Knowledges/tree/master/Examples/React/react-router-usage

利用示例

本文要实现的性能是大家常常遇到的场景,就是要管制不同的用户角色来拜访不同的页面,这里总共有四个页面:

  1. /index: 网站首页
  2. /login: 登录页
  3. /backend:后盾页面
  4. /admin:治理页面

另外还有三种角色:

  1. 未登录用户:只能拜访网站首页/index和登录页/login
  2. 普通用户:能够拜访网站首页/index,登录页/login和后盾页面/backend
  3. 管理员:能够拜访治理页面/admin和其余所有页面

引入React-Router

要实现路由鉴权,咱们还得一步一步来,咱们先用React-Router搭建一个简略的带有这几个页面的我的项目。咱们间接用create-react-app创立一个新我的项目,而后建了一个pages文件夹,外面放入咱们后面说的那几个页面:

咱们页面先写简略点,先写个题目吧,比方这样:

import React from 'react';function Admin() {  return (    <h1>管理员页面</h1>  );}

其余几个页面也是相似的。

而后咱们就能够在App.js外面引入React-Router做路由跳转了,留神咱们在浏览器上应用的是react-router-dom,新版的React-Router将外围逻辑层和展现层离开了,外围逻辑会解决路由匹配等,展现层会解决理论的跳转和路由变动的监听,之所以这么分,是因为React-Router不仅仅须要反对浏览器,还须要反对React Native,这两个平台的监听和跳转是不一样的,所以当初React-Router上面有好几个包了:

react-router:外围逻辑解决,提供一些专用的基类

react-router-dom:具体实现浏览器相干的路由监听和跳转

react-router-native:具体实现RN相干的路由监听和跳转

在理论应用时,咱们个别不须要援用react-router,而是间接用react-router-dom就行,因为它本人会去援用react-router。上面咱们在我的项目外面引入react-router-dom

import React from 'react';import {  BrowserRouter as Router,  Switch,  Route,} from "react-router-dom";import Home from './pages/Home';import Login from './pages/Login';import Backend from './pages/Backend';import Admin from './pages/Admin';function App() {  return (    <Router>      <Switch>        <Route path="/login" component={Login}/>        <Route path="/backend" component={Backend}/>        <Route path="/admin" component={Admin}/>        <Route path="/" component={Home}/>      </Switch>    </Router>  );}export default App;

而后能够在Home页面用Link加上跳转到其余页面的链接,这样就能够跳转了:

import React from 'react';import { Link } from 'react-router-dom';function Home() {  return (    <>      <h1>首页</h1>      <ul>        <li><Link to="/login">登录</Link></li>        <li><Link to="/backend">后盾</Link></li>        <li><Link to="/admin">管理员</Link></li>      </ul>    </>  );}export default Home;

到当初咱们的利用运行起来是这样的:

模块划分

尽管咱们的跳转实现了,然而所有人都能够拜访任何页面,咱们后面的需要是要依据登录的角色限度拜访的页面的,在写代码前,咱们先来思考下应该怎么做这个。当然最直观最简略的办法就是每个页面都检测下以后用户的角色,匹配不上就报错或者跳回首页。咱们当初只有几个页面,这样做如同也还好,然而如果咱们的利用变大了,页面变多了,每个页面都来一次检测就显得很反复了,所以咱们应该换个角度来思考这个问题。

认真一看,其实咱们总共就三种角色,对应三种不同的权限,这三个权限还有层级关系,高级别的权限蕴含了低级别的权限,所以咱们的页面也能够依照这些权限分为三种:

  1. 公共页面:所有人都能够拜访,没登录也能够拜访,包含网站首页和登录页
  2. 一般页面:一般登录用户能够拜访的页面
  3. 管理员页面:只有管理员能力拜访的页面

为了好治理这三种页面,咱们能够将他们抽取成三个文件,放到一个独立的文件夹routes外面,三个文件别离命名为publicRoutes.jsprivateRoutes.jsadminRoutes.js

对于每个路由文件,咱们能够将这类路由组织成数组,而后export进来给里面调用,比方publicRoutes.js

import Login from '../pages';import Home from '../pages/Home';const publicRoutes = [  {    path: '/login',    component: Login,    exact: true,  },  {    path: '/',    component: Home,    exact: true,  },];export default publicRoutes;

而后咱们里面应用的中央间接改为:

import publicRoutes from './routes/publicRoutes';function App() {  return (    <Router>      <Switch>        {publicRoutes.map(          ({path, component, ...routes}) =>             <Route key={path} path={path} component={component} {...routes}/>        )}        <Route path="/backend" component={Backend}/>        <Route path="/admin" component={Admin}/>      </Switch>    </Router>  );}

这样咱们的App.js外面就不会有简短的路由路由列表了,而是只须要循环一个数组就行了。然而对于须要登录能力拜访的页面和管理员页面咱们不能间接渲染Route组件,咱们最好再封装一个高级组件,将鉴权的工作放到这个组件外面去,这样咱们一般的页面在实现时就不须要关怀怎么鉴权了。

封装高级组件

要封装这个鉴权组件思路也很简略,后面咱们将publicRoutes间接拿来循环渲染了Route组件,咱们的鉴权组件只须要在这个根底上再加一个逻辑就行了:在渲染真正的Route组件前先检查一下以后用户是否有对应的权限,如果有就间接渲染Route组件,如果没有就返回某个页面,能够是登录页或者后盾首页,具体依据本人我的项目需要来。所以咱们的路由配置文件privateRoutes.jsadminRoutes.js外面的路由会比publicRoutes.js的多两个参数:

// privateRoutes.jsimport Backend from '../pages/Backend';const privateRoutes = [  {    path: '/backend',    component: Backend,    exact: true,    role: 'user',       // 以后路由须要的角色权限    backUrl: '/login'   // 不满足权限跳转的路由  },];export default privateRoutes;

adminRoutes.js是相似的写法:

// adminRoutes.jsimport Admin from '../pages/Admin';const adminRoutes = [  {    path: '/admin',    component: Admin,    exact: true,    role: 'admin',       // 须要的权限是admin    backUrl: '/backend'  // 不满足权限跳回后盾页面  },];export default adminRoutes;

而后就能够写咱们的高级组件了,咱们将它命名为AuthRoute吧,留神咱们这里假如的用户登录时后端API会返回给咱们以后用户的角色,一个用户可能有多个角色,比方普通用户的角色是['user'],管理员的角色是['user', 'admin'],具体的权限验证逻辑要看本人我的项目权限的设计,这里只是一个例子:

// AuthRoute.jsimport React from 'react';import { Route, Redirect } from 'react-router-dom';function AuthRoute(props) {  const {    user: {      role: userRole    },    role: routeRole,    backUrl,    ...otherProps  } = props;  // 如果用户有权限,就渲染对应的路由  if (userRole && userRole.indexOf(routeRole) > -1) {    return <Route {...otherProps} />  } else {    // 如果没有权限,返回配置的默认路由    return <Redirect to={backUrl} />  }}export default AuthRoute;

而后用咱们的AuthRoute的渲染adminRoutesprivateRoutes:

// ... 省略其余代码 ...{privateRoutes.map(  (route) => <AuthRoute key={route.path} {...route}/>)}{adminRoutes.map(  (route) => <AuthRoute key={route.path} {...route}/>)}

登录设置权限

在咱们的AuthRoute外面用到了user: { role }这个变量,然而咱们还没设置它。实在我的项目中个别是登录的时候后端API会返回以后用户的角色,而后前端将这个权限信息保留在一些状态管理工具外面,比方Redux。咱们这里间接在Login页面写死两个按钮来模仿这个权限了,用户的配置就用根组件的state来治理了,Login页面的两个按钮会扭转对应的state

import React from 'react';import { Link } from 'react-router-dom';function Login(props) {  const {loginAsUser, loginAsAdmin, history} = props;  const userLoginHandler = () => {    loginAsUser();      // 调用父级办法设置用户权限    history.replace('/backend');     // 登录后跳转后盾页面  }  const adminLoginHandler = () => {    loginAsAdmin();     // 调用父级办法设置管理员权限    history.replace('/admin');     // 登录后跳转管理员页面  }  return (    <>      <h1>登录页</h1>      <button onClick={userLoginHandler}>普通用户登录</button>      <br/><br/>      <button onClick={adminLoginHandler}>管理员登录</button>      <br/><br/>      <Link to="/">回首页</Link>    </>  );}export default Login;

到这里咱们这个简略的路由鉴权就实现了,具体跑起来成果如下:

本文全副代码曾经上传GitHub,大家能够拿下来玩玩:https://github.com/dennis-jiang/Front-End-Knowledges/tree/master/Examples/React/react-router-usage

总结

  1. React-Router能够用来治理前端的路由跳转,是React生态外面很重要的一个库。
  2. React-Router为了同时反对浏览器和React-Native,他分拆成了三个包react-router外围包,react-router-dom浏览器包,react-router-native反对React-Native。应用时不须要引入react-router,只须要引入须要的平台包就行。
  3. 对于须要不同权限的路由,咱们能够将他们拎进去分好类,独自建成一个文件,如果路由不多,放在一个文件导出多个数组也行。
  4. 对于须要鉴权的路由,咱们能够用一个高级组件将权限校验的逻辑封装在外面,其余页面只须要加好配置,齐全不必关怀鉴权的问题。

本文内容偏简略,作为相熟React-Router的用法还不错,然而咱们不能只会用,还要晓得他的原理。下篇文章咱们就来看看React-Router的源码外面蕴藏了什么神秘,大家能够点个关注不迷路,哈哈~

参考资料

官网文档:https://reactrouter.com/web/guides/quick-start

GitHub源码地址:https://github.com/ReactTraining/react-router/tree/master/packages

文章的最初,感激你破费贵重的工夫浏览本文,如果本文给了你一点点帮忙或者启发,请不要悭吝你的赞和GitHub小星星,你的反对是作者继续创作的能源。

作者博文GitHub我的项目地址: https://github.com/dennis-jiang/Front-End-Knowledges