前端权限方案(React)

62 阅读1分钟

在React项目中的权限方案:巧妙利用权限配置和元素的嵌套结构,自然实现权限逻辑,从而避免因为权限标志需要唯一导致过长的问题...

核心代码如下:

interface Permission {
  key: string;
  children?: Permission[];
}

const PermissionContext = createContext<Permission[]>([]);

function usePermissionContext() {
  const permission = useContext(PermissionContext);
  return permission;
}

// 控制元素显示隐藏的权限容器
function PermissionContainer(props: {
  permissionList?: Permission[];
  permissionKey?: string;
  children: ReactNode;
  fallback?: ReactNode;
}) {
  const { permissionList, permissionKey, children, fallback } = props;
  if (permissionList) {
    return (
      <PermissionContext.Provider value={permissionList}>
        {children}
      </PermissionContext.Provider>
    );
  }
  if (permissionKey) {
    const permissions = usePermissionContext();
    if (permissions) {
      const permission = permissions.find(item => item.key === permissionKey);
      if (permission) {
        return (
          <PermissionContext.Provider value={permission.children ?? []}>
            {children}
          </PermissionContext.Provider>
        );
      }
    }
  }

  return fallback;
}

在菜单如下使用

<PermissionContainer 
    permissionList={[ 
        { 
            key: 'brc__menu', 
            children: [ 
               { 
                    key: 'brc_menu', 
                    children: [ 
                        { 
                            key: 'psp__menu', 
                        }, 
                    ], 
               }
           ]
        } 
 > 
         <CustomMenu routes={originalRoutes}></CustomMenu> 
</PermissionContainer>

菜单定义如下

function MenuItem(props: any) { 
    // route为元素的路由配置对象,有属性:code(权限标志), title(菜单标题), routes(子菜单)
    const { route } = props; 
    const { code } = route; 
    if (!route.routes) { 
        return ( 
            <PermissionContainer permissionKey={code}> 
                <Menu.Item key={route.code}>
                    {route.title}
                </Menu.Item> 
            </PermissionContainer> 
        ); 
    } 
    return ( 
        <PermissionContainer permissionKey={code}> 
            <Menu.SubMenu key={route.code} title={route.title}> 
                {route.routes.map(item => { 
                    const { title } = item; 
                    return <MenuItem key={route.code} route={item}></MenuItem>; 
                })} 
            </Menu.SubMenu> 
        </PermissionContainer> 
    ); 
}