react router v6权限控制



前言

上一篇文章写了react router v6怎么做类似vue的路由守卫(没看过的小伙伴可了解一下: react router v6路由守卫权限控制),这篇主要写怎么控制具体的用户和页面的权限


提示:以下是本篇文章正文内容,下面案例可供参考

一、个人需求

需要根据不同的权限进行控制

二、实现思路

1.需要确定先控制什么

当然是用户有木有登录了

当然也有一些是不需要登录也能进入的,所以需要先把需要登录的路由和不需要登录的路由区分。

2.区分需要权限路由和不需要权限路由

2-1.不需要权限路由

/**
 * 不需要权限的路径
 */
const otherPaths = [
	'/auth/login',
	'/auth/forgotten',
	'/auth/register',
]

2-2.需要权限路由

/**
 * 需要权限的路由
 */
const permissionPaths = [
	'/application/home'
]

我这里先随意放了几个路由,具体是什么路由需要小伙伴根据自己的项目来定

3. 实现思路

3-1. onRouterBefore函数定义

上一篇讲了在onRouterBefore里面进行权限判断,这里具体讲一下怎么实现。

/**
 * before router 可在这加入权限判断
 */
const onRouterBefore = (location: Location) => {
	let { pathname, search } = location
	pathname = resolveRedirect(pathname)
	const userInfo = getLocalItem('userInfo') || {}
	// 没有token,并且不是不需要权限的几个路由
	if (!userInfo.token && !otherPaths.includes(pathname)) {
		// 返回登录
		return '/auth/login'
	} else {
		return pathname
	}
}

到这里就基本实现了是否登录的权限判断。当然了,具体项目中不会这么简单,肯定还有其他权限的判断,那么让我们继续!

3-2. 权限判断先后顺序确定

我们上面确定了,优先处理token,其实这是一个项目最基础的权限,也是需要最先处理的,只有登录之后才能获取对应权限,所以需要先判断用户权限,再判断页面权限。所以这就需要用到了洋葱模型概念。

从外层一层一层执行到内部,再从内部一层一层执行到外部

3-3. 实现一个compose方法

export default function compose(...funcs: Function[]) {
  if (funcs.length === 0) {
    // infer the argument type so it is usable in inference down the line
    return <T>(arg: T) => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce(
    (a, b) =>
      (...args: any) =>
        a(b(...args))
  )
}

具体实现大同小异基本都是用到了reduce来实现,可参考redux的实现 compose

4. 具体实现

这里就拿页面权限举例。

/**
 * 页面拦截
 */
const pageInterceptor = ({
	pathname,
	userInfo
}: {
	pathname: string,
	userInfo: UserInfo
}) => {
	const { isAdmin } = userInfo
	if (!isAdmin && permissionPaths.includes(pathname)) {
		// 没有权限,并且进入需要权限的页面
		return '/default/noPermission'
	}
	return pathname
}

页面拦截就拦截用户没有权限进入需要权限的页面,就跳转需要跳转的路由,这边直接跳转了一个无权限页面,也可以跳转404,看各自需求。

4-1. 改造onRouterBefore函数

/**
 * before router 可在这加入权限判断
 */
const onRouterBefore = (location: Location) => {
	let { pathname, search } = location
	pathname = resolveRedirect(pathname)
	const userInfo = getLocalItem('userInfo') || {}
	// 没有token,并且不是不需要权限的几个路由
	if (!userInfo.token && !otherPaths.includes(pathname)) {
		// 返回登录
		return '/auth/login'
	} else {
		// 注意compose是先执行userInterceptor函数再执行pageInterceptor,参数需要传递过去。
		const nextPath = compose(
			pageInterceptor,
			userInterceptor
		)({ pathname, userInfo })
		return nextPath ?? pathname
	}
}

到这里基本就实现了页面,用户权限的判断,我写的例子只是满足最基础的拦截,具体怎么拦截可以看具体项目的需要

总结

整个项目权限做下来,可能在洋葱模型上面跨度有点大,但这个实际是很好的处理了不同权限之间的处理。不然全是if else这样的话,功能不够单一,而且后续维护也难,所以用这个模型,后续新增一个逻辑判断完全可以新增一个函数,至少保障了其他函数的单一性。希望这能给不知道怎么用react router v6做拦截的小伙伴一点点思路。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐