在React应用开发过程中,权限校验是控制用户操作范围、页面元素展示的核心能力,很多场景下我们需要封装一个返回布尔值的权限校验函数,快速判断当前用户是否具备对应权限,从而决定后续的逻辑走向。
权限校验函数的核心设计思路
权限校验函数返回布尔值的本质是接收权限标识,对比当前用户持有的权限集合,最终返回是否匹配的判定结果。设计时需要先明确两个基础前提:一是当前用户的权限数据如何存储,二是权限标识的匹配规则是什么。
权限数据的存储方式
通常用户的权限数据会在登录后通过接口获取,常见的存储位置有两种:
- 存储在React的上下文(Context)中,适合全局共享的场景
- 存储在状态管理库(如Redux、Zustand)中,适合复杂项目的状态同步
如果是小型项目,也可以暂时将权限数据存储在本地存储中,但需要注意本地存储的数据是可以被用户修改的,敏感场景不建议使用这种方式。
基础权限校验函数实现
假设我们已经从接口获取到了当前用户的权限列表,存储在变量user_permissions中,权限标识为字符串类型,那么最基础的校验函数可以写成如下形式:
// 用户权限列表,实际项目中从接口获取后存储
const user_permissions = ['user:add', 'user:edit', 'order:view'];
/**
* 权限校验函数
* @param {string} permission 需要校验的权限标识
* @returns {boolean} 是否拥有该权限
*/
function checkPermission(permission) {
// 判断用户权限列表中是否包含目标权限
return user_permissions.includes(permission);
}
// 调用示例
console.log(checkPermission('user:add')); // 输出 true
console.log(checkPermission('user:delete')); // 输出 false
支持多权限校验的扩展实现
实际业务中经常需要判断用户是否同时拥有多个权限,或者拥有多个权限中的任意一个,这时候可以对基础函数做扩展,支持传入权限数组,同时增加匹配模式的参数。
const user_permissions = ['user:add', 'user:edit', 'order:view'];
/**
* 扩展权限校验函数
* @param {string|string[]} permission 需要校验的权限标识,支持单个字符串或字符串数组
* @param {string} mode 匹配模式,all表示全部拥有,some表示拥有任意一个,默认some
* @returns {boolean} 是否拥有对应权限
*/
function checkPermission(permission, mode = 'some') {
// 如果是单个权限标识,转换为数组处理
const targetPermissions = Array.isArray(permission) ? permission : [permission];
if (mode === 'all') {
// 判断用户是否拥有所有目标权限
return targetPermissions.every(p => user_permissions.includes(p));
} else {
// 判断用户是否拥有任意一个目标权限
return targetPermissions.some(p => user_permissions.includes(p));
}
}
// 调用示例
console.log(checkPermission(['user:add', 'user:edit'])); // 输出 true,拥有任意一个
console.log(checkPermission(['user:add', 'user:edit'], 'all')); // 输出 true,全部拥有
console.log(checkPermission(['user:add', 'user:delete'], 'all')); // 输出 false,缺少user:delete
在React组件中使用权限校验函数
封装好返回布尔值的权限校验函数后,我们可以将其和React组件结合,实现元素的条件渲染。比如我们可以封装一个权限校验的高阶组件,或者直接在组件内调用函数判断。
条件渲染示例
import React from 'react';
// 假设checkPermission已经通过上下文或者导入的方式获取
const user_permissions = ['user:add', 'user:edit', 'order:view'];
function checkPermission(permission) {
return user_permissions.includes(permission);
}
function UserManagePage() {
return (
<div>
<h3>用户管理页面</h3>
<div>
{/* 只有拥有user:add权限才展示新增按钮 */}
{checkPermission('user:add') && (
<button>新增用户</button>
)}
{/* 只有拥有user:delete权限才展示删除按钮 */}
{checkPermission('user:delete') && (
<button>删除用户</button>
)}
</div>
</div>
);
}
export default UserManagePage;
结合Context实现全局权限获取
如果项目是多个组件都需要使用权限校验函数,建议将用户权限和校验函数通过Context提供给所有子组件,避免每个组件都单独导入权限数据。
import React, { createContext, useContext, useState, useEffect } from 'react';
// 创建权限上下文
const PermissionContext = createContext({
permissions: [],
checkPermission: () => false
});
// 权限上下文提供者组件
export function PermissionProvider({ children }) {
const [permissions, setPermissions] = useState([]);
// 模拟登录后获取权限数据
useEffect(() => {
// 实际项目中替换为真实的接口请求
const mockPermissions = ['user:add', 'user:edit', 'order:view'];
setPermissions(mockPermissions);
}, []);
// 封装校验函数,返回布尔值
const checkPermission = (permission, mode = 'some') => {
const targetPermissions = Array.isArray(permission) ? permission : [permission];
if (mode === 'all') {
return targetPermissions.every(p => permissions.includes(p));
}
return targetPermissions.some(p => permissions.includes(p));
};
return (
<PermissionContext.Provider value={{ permissions, checkPermission }}>
{children}
</PermissionContext.Provider>
);
}
// 自定义Hook,方便组件内获取权限校验能力
export function usePermission() {
const context = useContext(PermissionContext);
if (!context) {
throw new Error('usePermission必须在PermissionProvider内使用');
}
return context;
}
之后在组件中就可以通过自定义Hook获取校验函数:
import React from 'react';
import { usePermission } from './PermissionContext';
function OrderPage() {
const { checkPermission } = usePermission();
return (
<div>
<h3>订单管理页面</h3>
{checkPermission('order:view') ? (
<p>这里是订单列表内容</p>
) : (
<p>您没有查看订单的权限</p>
)}
</div>
);
}
export default OrderPage;
注意事项
在实现权限校验函数时需要注意几个常见问题:一是权限标识的命名要规范,建议采用模块:操作的格式,避免标识冲突;二是不要在权限校验函数内做异步操作,保证函数始终同步返回布尔值,避免组件渲染出现异常;三是如果用户权限可能动态变化,需要在权限更新后同步更新存储的权限数据,保证校验结果准确。