0


深入浅出:实现前端菜单权限控制的策略详解(结尾附vue3完整示例代码)

引言

在构建企业级Web应用时,菜单权限控制很关键。前端层面实现菜单权限控制,确保系统安全性的同时提升用户体验。

@[一、权限模型和数据结构]

##一、权限模型和数据结构

  1. 权限模型:常见的权限模型有基于角色的权限控制(RBAC,Role-Based Access Control),即用户通过角色与权限关联,角色再与具体的菜单项绑定。菜单结构一般采用树形结构,方便递归渲染与权限过滤。

  2. 数据对接:前端通过与后端API交互,获取当前登录用户的角色及其所拥有的菜单权限数据。这部分数据通常包括菜单ID、名称、URL、父节点ID以及是否可见、是否可访问等权限标识。

  3. 数据处理:拿到权限数据后,前端需要将其转换为易于操作的数据结构,例如数组或对象。可以按照菜单层级构建嵌套数组,便于递归生成菜单。

二、前端权限控制实现策略

  1. 渲染前过滤

在渲染菜单组件前,根据用户权限数据对原始菜单数据进行筛选,去除无权限访问的菜单项。这是一种主动过滤的方式,可以减少无用DOM元素的生成,降低内存占用。

function filterMenusByPermission(menus, permissions) {
  return menus.filter(menu => permissions.includes(menu.id) && menu.visible);
}
  1. 渲染时控制

在菜单组件的渲染函数内部,针对每个菜单项判断其权限属性,决定是否渲染。这种方式下,即使用户没有权限的菜单项也会被创建成DOM元素,但在最终呈现时会被隐藏。

function MenuItem({ menu }) {
  if (!menu.accessible) return null; // 权限不足,不渲染此菜单项
  
  return <div>{menu.name}</div>;
}

function MenuList({ menus }) {
  return (
    <ul>
      {menus.map(menu => (
        <MenuItem key={menu.id} menu={menu} />
      ))}
    </ul>
  );
}
  1. 动态路由控制

在使用了路由系统的项目中,还可以结合路由配置实现权限控制。为每个路由配置对应的权限标识,然后在路由守卫(如Vue中的beforeEach钩子函数)中进行拦截和跳转处理。

router.beforeEach((to, from, next) => {
  const hasPermission = checkUserPermission(to.meta.permission); // 自定义校验函数
  
  if (hasPermission) {
    next();
  } else {
    next({ name: 'Unauthorized' }); // 无权限时重定向至未经授权页面
  }
});

三、实时权限变更应对

考虑到权限可能在用户使用过程中动态变更,前端还需要监听权限变更事件,及时刷新菜单数据和路由控制。例如,可以通过WebSocket、EventBus或定期轮询等方式接收来自后端的权限更新通知。

四:示例-使用Vue3语法实现前端菜单权限控制

<template>
  <ul class="menu-list">
    <li v-for="menu in filteredMenus" :key="menu.id">
      <router-link :to="menu.path">{{ menu.name }}</router-link>
      <ul v-if="menu.children">
        <li v-for="child in menu.children" :key="child.id">
          <router-link :to="child.path">{{ child.name }}</router-link>
        </li>
      </ul>
    </li>
  </ul>
</template>

<script setup lang="ts">
import { ref, computed, useRouter } from 'vue';
import { useStore } from '@/stores/index'; // 存在一个Vuex Store

// 从Vuex Store中获取用户权限和菜单数据
const store = useStore();
const userPermissions = ref<string[]>(store.getters.getUserPermissions);
const menuData = ref<any[]>(store.getters.getMenuData);

// 计算过滤后的菜单
const filteredMenus = computed(() => {
  return menuData.value.filter(menu => 
    userPermissions.value.some(permission => menu.permission.includes(permission)) &&
    menu.visible
  ).map(menu => ({
    ...menu,
    children: filterChildren(menu.children),
  }));
});

const filterChildren = (children: any[] = []) => {
  return children.filter(child =>
    userPermissions.value.some(permission => child.permission.includes(permission)) &&
    child.visible
  );
};

// 动态路由控制
const router = useRouter();
router.beforeEach(async (to, from, next) => {
  const hasPermission = to.meta.permission?.some(permission =>
    userPermissions.value.includes(permission)
  );

  if (hasPermission || !to.meta.permission?.length) {
    next();
  } else {
    next({ name: 'Unauthorized' });
  }
});
</script>

首先,可以从Vuex Store中获取用户权限和菜单数据,并通过ref和computed来管理这些数据。接着,计算出用户有权限访问的菜单项,并在模板中进行渲染。

同时,也可以利用Vue Router的beforeEach全局守卫实现了动态路由权限控制。在实际项目中,请确保userPermissions和menuData是从正确的地方获取的,可能是Vuex Store,也可能是API接口。


本文转载自: https://blog.csdn.net/weixin_59969446/article/details/136843886
版权归原作者 飞108 所有, 如有侵权,请联系我们删除。

“深入浅出:实现前端菜单权限控制的策略详解(结尾附vue3完整示例代码)”的评论:

还没有评论