「从零开始的 Vue 3 系列」:第九章——vue3中实‘动态路由‘与“权限管理“

前言

本系列将从零开始,系统性地介绍 Vue 3 的常用 API,逐步深入每个核心概念与功能模块。通过详尽的讲解与实战演示,帮助大家掌握 Vue 3 的基础与进阶知识,最终具备独立搭建完整 Vue 3 项目的能力。

**思路:**动态路由实现就是前端登录获取用户信息->后端验证与权限获取->返回权限数据->前端动态生成路由-->权限控制

那么项目中是如何实现呢:

定义基础路由

cpp 复制代码
import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  { path: '/', component: Home },
  { path: '/login', component: Login },
  // 其他公共路由
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

在用户登录时,从后端获取用户的权限数据。权限数据通常包含用户可以访问的路由或角色信息。

动态路由与菜单权限:

动态添加路由(一般是菜单权限):

根据从后端获取的权限数据,使用 Vue Router 的 addRoute 方法动态添加路由。例如:

方法一般都要挂在到main.js中,可以将动态路由方法写到新建的js中,然后将这个js引入进main.js

cpp 复制代码
function addDynamicRoutes(permissions) {
  const dynamicRoutes = permissions.map(permission => {
    return {
      path: permission.path,
      component: () => import(`../views/${permission.component}`),
    };
  });

  dynamicRoutes.forEach(route => {
  	//这里使用addRoute添加到路由
    router.addRoute(route);
  });
}

设置路由守卫:

使用路由守卫(如 beforeEach)来验证用户是否有权限访问某个路由。如果没有权限,可以重定向到登录页面或错误页面。

cpp 复制代码
router.beforeEach((to, from, next) => {
  const isAuthenticated = // 判断用户是否已认证
  const hasPermission = // 判断用户是否有访问该路由的权限

  if (!isAuthenticated && to.path !== '/login') {
    next('/login');
  } else if (isAuthenticated && !hasPermission) {
    next('/403'); // 无权限页面
  } else {
    next();
  }
});

按钮权限:

1.基于指令的权限控制

你可以创建自定义指令来控制按钮的显示或禁用,这样可以在模板中方便地使用。

cpp 复制代码
const app = Vue.createApp({});

app.directive('permission', {
  mounted(el, binding) {
    const userPermissions = binding.instance.$data.userPermissions; // 假设从组件实例中获取用户权限
    if (!userPermissions.includes(binding.value)) {
      el.style.display = 'none'; // 隐藏没有权限的按钮
    }
  }
});

app.component('my-component', {
  data() {
    return {
      userPermissions: ['view', 'edit'] // 用户权限示例
    };
  },
  template: `
    <button v-permission="'edit'">Edit</button>
    <button v-permission="'delete'">Delete</button>
  `
});

app.mount('#app');

2.使用 Vuex 进行权限管理

在更复杂的应用中,可能需要使用 Vuex 来集中管理用户权限,并在组件中获取权限状态。

cpp 复制代码
const store = Vuex.createStore({
  state() {
    return {
      userPermissions: ['view', 'edit']
    };
  },
  getters: {
    hasPermission: (state) => (permission) => {
      return state.userPermissions.includes(permission);
    }
  }
});

const app = Vue.createApp({
  computed: {
    canEdit() {
      return this.$store.getters.hasPermission('edit');
    },
    canDelete() {
      return this.$store.getters.hasPermission('delete');
    }
  },
  template: `
    <button v-if="canEdit">Edit</button>
    <button v-if="canDelete">Delete</button>
  `
});

app.use(store).mount('#app');

3.使用计算属性或方法

在模板中使用计算属性或方法来决定按钮是否显示或禁用。

cpp 复制代码
const app = Vue.createApp({
  data() {
    return {
      userPermissions: ['view', 'edit'] // 用户权限示例
    };
  },
  methods: {
    hasPermission(permission) {
      return this.userPermissions.includes(permission);
    }
  },
  template: `
    <button v-if="hasPermission('edit')">Edit</button>
    <button v-if="hasPermission('delete')">Delete</button>
  `
});

app.mount('#app');

4.基于组件封装

你可以创建一个权限按钮组件,内部包含权限逻辑,方便在应用中多次复用。

cpp 复制代码
app.component('permission-button', {
  props: ['permission'],
  template: `
    <button v-if="hasPermission">{{ permission }}</button>
  `,
  computed: {
    hasPermission() {
      return this.$root.userPermissions.includes(this.permission); // 假设从根实例获取用户权限
    }
  }
});

// 在根实例中定义用户权限
const app = Vue.createApp({
  data() {
    return {
      userPermissions: ['view', 'edit']
    };
  },
  template: `
    <permission-button permission="edit"></permission-button>
    <permission-button permission="delete"></permission-button>
  `
});

app.mount('#app');

总结:根据应用的复杂程度,你可以选择以上不同的方法来实现按钮权限控制。对于简单的权限检查,自定义指令或计算属性可能就足够了;而对于复杂的权限系统,可以考虑使用 Vuex 或封装组件的方式。这样不仅可以提高代码的可维护性,还可以保持代码的可读性和复用性。

ps:以上内容仅为本人对 vue3的个人理解,如有不足之处,欢迎大家指正与交流,共同进步。
相关推荐
腾讯TNTWeb前端团队38 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom6 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom6 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom6 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试