React 封装高阶组件 做路由权限控制
路由权限控制做什么?
主要就是判断用户是否登陆,只有登陆获取到有效的token,才能跳转到页面。
思路:
判断是否有 token ,如果有 token 则返回正常的组件,如果没有 token 则跳转到登陆页。
实现:
因为是ts所以先定义参数类型,这里的ReactElement
代表的是一个 React 元素例如:<div/> 或者是组件。之后我们获取到 token ,通过 token 的有无判断跳转到相应页面。
代码:
封装高阶组件:
interface AuthRouteProps {
children: React.ReactElement;
}
export function AuthRoute({ children }: AuthRouteProps) {
const token = getToken();
if (token) {
return <>{children}</>;
} else {
// 使用 Navigate 组件进行导航
message.error("请先登录");
return <Navigate to="/login" />;
}
}
在路由配置文件中,引入封装的组件,例如:
children: [
{
index: true,
element: <Chat />
},
{
path: '/paint',
element: (
<AuthRoute><Paint /></AuthRoute>
)
},
{
path: '/me',
element: <div>我的</div>
}
]
缺点:
目前只是通过判断 token 有无,如果 token 失效了却还是会跳转,如果是跳转到的页面需要携带token 则可以在响应拦截器中进行处理:token 会发给后端,后端通过解密后来判断用户是否存在
// 添加响应拦截器
request.interceptors.response.use(
function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response.data;
},
function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
if(error.status === 401){
removeToken()
router.navigate('/login')
window.location.reload()
}
return Promise.reject(error);
}
);
如果只是单纯的跳转页面的话要进行改造也是发一个请求给后端,后端通过处理返回给前端 token 是否有效:
export async function AuthRoute({children}){
const token = getToken();
// 模拟请求发给后端token
const res = await getUserInfo({ token });
if (res.data.code) {
return <>{children}</>;
} else {
return <Navigate to="/login" replace />;
}
}
所以要通过具体的业务来处理用户登陆和 token 是否有效。
比较:
通过这样的方式写和直接在访问页面中判断token有什么区别?
直接在访问页面时判断:这种方式通常是在页面组件加载或渲染时进行的,即在用户已经导航到该页面后才进行检查。
使用AuthRoute
组件:判断是在路由跳转之前进行的。当用户尝试访问受保护的路由时,AuthRoute
组件会首先检查token,然后决定是否允许访问或进行重定向。