likes
comments
collection
share

前端框架对比系列之vue和react的按钮权限控制(一)

作者站长头像
站长
· 阅读数 53

前言

  1. 如果系统角色是固定的,我们可以将按钮权限类似角色一样配置在routes 里面;
  2. 通过动态添加路由的方法,即调用后端接口返回当前用户角色拥有的所有页面菜单信息,将菜单格式化成路由之后,再动态的添加到前端系统中,这种方式会更加灵活。

1. vue2 实现页面的角色权限按钮控制

将用户角色按钮事先配置在routes里面

定义 routes

首先定义好系统的路由,在meta里面定义每个角色所拥有的按钮列表, 当前涉及到权限讨论的页面是 /about页面。这里我们给 admin master developer 等三个角色配置了不同的按钮权限。

import Home from "../components/Home.vue"

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: "/home",
    name: "home",
    component: Home,
    meta: {
      needLogin: false, // 不需要登录
      title: "首页",
    }
  },
  {
    path: "/login",
    name: "login",
    component: () => import(/* webpackChunkName: "login" */ "../components/Login.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 不需要登录
      title: "登录"
    }
  },
  {
    path: "/about",
    name: "about",
    component: () => import(/* webpackChunkName: "about" */ "../components/About.vue"), // 路由懒加载
    meta: {
      needLogin: true, // 需要登录
      title: "关于",
      roles: ['admin', 'master', 'developer'], // 当前页面只有 admin 权限才能进入
      btns: {
        admin: ["add", "delete", "edit", "select"], // admin 有增、删、改、查按钮
        master: ["edit", "select"], // master 有编辑、查看按钮
        developer: ["select"], // developer 只有查看按钮
      }
    }
  },
  {
    path: "/nopermission", // 没权限就进入该页面
    name: "NoPermission",
    component: () => import(/* webpackChunkName: "about" */ "../components/NoPermission.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 需要登录
      title: "暂无权限",
    },
  }
];

export default routes;

方案 1 : 直接通过v-if 指令控制按钮的隐藏和显示

主要思路:初始化当前页面时,先通过store拿到缓存的userInfo信息(信息中包含有当前的登陆的用户的角色权限,比如 admin 权限)以及通过$route.meta获取配置的按钮权限信息btns。通过v-if 指令控制按钮的现实与隐藏。

<template>
  <div class="about">
    <h4>关于 - about</h4>
    <div class="user-list">
      <h3>1. 通过v-if 控制按钮权限</h3>
      <button v-if="showAdd">
        add
      </button>
      <button v-if="showDelete">
        delete
      </button>
      <button v-if="showEdit">
        edit
      </button>
      <button v-if="showSelect">
        select
      </button>
    </div>
  </div>
</template>

<script>
import store from '../store';
export default {
  computed: {
    userInfo() {
      return store.state.userInfo
    },
    showAdd() {
      return !this.$route?.meta.btns || this.$route?.meta.btns[this.userInfo.role].includes('add')
    },
    showDelete() {
      return !this.$route?.meta.btns || this.$route?.meta.btns[this.userInfo.role].includes('delete')
    },
    showEdit() {
      return !this.$route?.meta.btns || this.$route?.meta.btns[this.userInfo.role].includes('edit')
    },
    showSelect() {
      return !this.$route?.meta.btns || this.$route?.meta.btns[this.userInfo.role].includes('select')
    }
  }
}
</script>

<style>

</style>

方案 2 : 直接自定义指令实现按钮的权限控制

新建 btnAuth.js文件,实现自定义指令 v-btnAuth,在自定义指令中通过在bindupdate方法中获取传入的参数实现当前绑定的按钮的显示和隐藏。页面中的button 按钮中引入自定义的指令,并传入路由配置的按钮角色权限参数。

 // 页面中 button 引入自定义指令
 <h3>2. 自定义指令控制 directive</h3>
  <button v-btnAuth:add="$route.meta.btns[userInfo.role]">add</button>
  <button v-btnAuth:delete="$route.meta.btns[userInfo.role]">delete</button>
  <button v-btnAuth:edit="$route.meta.btns[userInfo.role]">edit</button>
  <button v-btnAuth:select="$route.meta.btns[userInfo.role]">select</button>
</div>
// directive/btnAuth.js
export default {
  install(Vue) {
    // 图片加载失败使用默认图片兜底指令
    Vue.directive('btnAuth', {
      bind(el, binding, vnode) {
        const btnName = binding.arg;
        const btns = binding.value;
        if (btns && btns.includes(btnName)) {
          el.style.display = "inline-block"; // 这里看情况给样式,不是none就可以
        } else {
          el.style.display = "none";
        }
      },
      update(el, binding, vnode, prevnode) {
        const btnName = binding.arg;
        const btns = binding.value;
        if (btns && btns.includes(btnName)) {
          el.style.display = "inline-block"; // 这里看情况给样式,不是none就可以
        } else {
          el.style.display = "none";
        }
      }
    });
  }
}
// main.js 全局中引入自定义的指令,使全局生效:
...
import btnDirective from './directive/btnAuth';
...
Vue.use(btnDirective);

new Vue({
  store,
  router,
  render: h => h(App),
}).$mount('#app')

2. vue3 实现页面的角色权限按钮控制

将用户角色按钮事先配置在routes里面

定义 routes

首先定义好系统的路由,在meta里面定义每个角色所拥有的按钮列表, 当前涉及到权限讨论的页面是 /about页面。这里我们给 admin master developer 等三个角色配置了不同的按钮权限。

import Home from "../components/Home.vue"

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: "/home",
    name: "home",
    component: Home,
    meta: {
      needLogin: false, // 不需要登录
      title: "首页"
    }
  },
  {
    path: "/login",
    name: "login",
    component: () => import(/* webpackChunkName: "login" */ "../components/Login.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 不需要登录
      title: "登录"
    }
  },
  {
    path: "/about",
    name: "about",
    component: () => import(/* webpackChunkName: "about" */ "../components/About.vue"), // 路由懒加载
    meta: {
      needLogin: true, // 需要登录
      title: "关于",
      roles: ['admin', 'master', 'developer'],
      btns: {
        admin: ["add", "delete", "edit", "select"], // admin 有增、删、改、查按钮
        master: ["edit", "select"], // master 有编辑、查看按钮
        developer: ["select"], // developer 只有查看按钮
      }
    }
  },
  {
    path: "/nopermission", // 没权限就进入该页面
    name: "NoPermission",
    component: () => import(/* webpackChunkName: "about" */ "../components/NoPermission.vue"), // 路由懒加载
    meta: {
      needLogin: false, // 需要登录
      title: "暂无权限",
    },
  }
];

export default routes;

方案 1 : 直接通过v-if 指令控制按钮的隐藏和显示

主要思路:初始化当前页面时,先通过store拿到缓存的userInfo信息(信息中包含有当前的登陆的用户的角色权限,比如 admin 权限)以及通过$route.meta获取配置的按钮权限信息btns。通过v-if 指令控制按钮的现实与隐藏。

<template>
  <div class="about">
    <h4>关于 - about</h4>
    <div class="user-list">
      <h3>1. 通过v-if 控制按钮权限</h3>
      <button v-if="showAdd">
        add
      </button>
      <button v-if="showDelete">
        delete
      </button>
      <button v-if="showEdit">
        edit
      </button>
      <button v-if="showSelect">
        select
      </button>
    </div>
  </div>
</template>

<script setup>
import {useRoute} from 'vue-router'
import { computed } from "vue";
import store from "@/store";
const $route = useRoute()

const userInfo = computed(() => {
  return store.state.userInfo
})

const showAdd = computed(() => {
  return !$route?.meta.btns || $route?.meta.btns[userInfo.value.role].includes('add')
})
const showDelete = computed(() => {
  return !$route?.meta.btns || $route?.meta.btns[userInfo.value.role].includes('delete')
})
const showEdit = computed(() => {
  return !$route?.meta.btns || $route?.meta.btns[userInfo.value.role].includes('edit')
})
const showSelect = computed(() => {
  return !$route?.meta.btns || $route?.meta.btns[userInfo.value.role].includes('select')
})

</script>
<style>
</style>

方案 2 : 直接自定义指令实现按钮的权限控制

新建 btnAuth.js文件,实现自定义指令 v-btnAuth,在自定义指令中通过在bindupdate方法中获取传入的参数实现当前绑定的按钮的显示和隐藏。页面中的button 按钮中引入自定义的指令,并传入路由配置的按钮角色权限参数。

<h3>2. 自定义指令控制 directive</h3>
  <button v-btnAuth:add="$route.meta.btns[userInfo.role]">add</button>
  <button v-btnAuth:delete="$route.meta.btns[userInfo.role]">delete</button>
  <button v-btnAuth:edit="$route.meta.btns[userInfo.role]">edit</button>
  <button v-btnAuth:select="$route.meta.btns[userInfo.role]">select</button>
</div>
// directive/btnAuth.js
export default function(app) {
  app.directive('btnAuth', {
    created(el, binding, vnode) {
      const btnName = binding.arg;
      const btns = binding.value;
      if (btns && btns.includes(btnName)) {
        el.style.display = "inline-block"; // 这里看情况给样式,不是none就可以
      } else {
        el.style.display = "none";
      }
    },
    beforeUpdate(el, binding, vnode, prevnode) {
      const btnName = binding.arg;
      const btns = binding.value;
      if (btns && btns.includes(btnName)) {
        el.style.display = "inline-block"; // 这里看情况给样式,不是none就可以
      } else {
        el.style.display = "none";
      }
    }
  });
}
// main.js 全局中引入自定义的指令,使全局生效:
...
import btnAuth from './directive/btnAuth';

const app = createApp(App);
btnAuth(app);
app.use(store);
app.use(router);
app.mount('#app')

3. react 实现页面的角色权限按钮控制

将用户角色按钮事先配置在routes里面

定义 routes

首先定义好系统的路由,在meta里面定义每个角色所拥有的按钮列表, 当前涉及到权限讨论的页面是 /about页面。这里我们给 admin master developer 等三个角色配置了不同的按钮权限。

import Home from "../pages/Home";
import About from "../pages/About";
import Login from "../pages/Login";
import NoPermission from "../pages/NoPermission";

const routes = [
  {
    path: "/home",
    component: Home,
    meta: {
      title: "首页",
      needLogin: false,
    },
  },
  {
    path: "/about",
    component: About,
    meta: {
      title: "关于",
      needLogin: true,
      roles: ['admin', 'master', 'developer'],
      btns: {
        admin: ["add", "delete", "edit", "select"], // admin 有增、删、改、查按钮
        master: ["edit", "select"], // master 有编辑、查看按钮
        developer: ["select"], // developer 只有查看按钮
      }
    },
  },
  {
    path: "/login",
    component: Login,
    meta: {
      title: "登录",
      needLogin: false,
    },
  },
  {
    path: "/nopermission",
    component: NoPermission,
    meta: {
      title: "没有访问权限页面",
      needLogin: false,
    },
  },
  {
    path: '/',
    redirect: '/home'
  },
];

export default routes;

方案 1 : 通过路由权限组件注入

在Auth组件给每个路由组件注入它相应权限的按钮 —— 核心就是通过用户信息里面的角色,给每个路由组件注入它相应权限的按钮。

页面的按钮通过Auth组件注入进来,在使用的时候通过props取出按钮列表与页面按钮匹配即可

...
return (
    <Route
      path={path}
      exact={exact}
      strict={strict}
      render={(props) => (
        <Component 
          {...props} 
          routes={routes} 
          // 给每个路由组件都注入btns
          btns={meta.btns && userInfo ? meta.btns[userInfo.role] : []} 
        />
      )}
    ></Route>
 );
import React from 'react'
import ButtonAutn from './components/ButtonAutn';

function About(props) {
  const { btns } = props || {};
  return (
    <div>
      <h3>react 权限按钮控制</h3>
      <div>
        <h3>1. 通过路由组件auth 传参,再对按钮进行条件验证权限</h3>
        {btns.includes("add") && <button>add</button>}
        {btns.includes("delete") && <button>delete</button>}
        {btns.includes("edit") && <button>edit</button>}
        {btns.includes("select") && <button>select</button>}
      </div>
    </div>
  )
}

export default About

方案 2 : 实现一个通用权限按钮组件控制

实现一个按钮组件ButtonAutn.jsx,获取传入的 props 参数来控制按钮组件的显示和隐藏。

页面中直接引入组件 <ButtonAutn type={'add'} btnName={'add'}/>

// ButtonAutn.jsx
import React from 'react'
import { useSelector } from 'react-redux'

function ButtonAutn(props) {
  const {type, btnName} = props || {};
  // 获取用户信息
  const userInfo = useSelector((state) => state.user);
  const showButton = function() {
    if(type === 'add') {
      return ['admin'].includes(userInfo.role)
    }
    if(type === 'delete') {
      return ['admin'].includes(userInfo.role)
    }
    if(type === 'edit') {
      return ['admin', 'master'].includes(userInfo.role)
    }
    if(type === 'select') {
      return ['admin', 'master', 'developer'].includes(userInfo.role)
    }
    return false
  }
  
  return showButton() ? (
    <button>{btnName}</button>
  ) : null;
}

export default ButtonAutn
<div>
    <h3>2. 通过实现一个权限按钮控制</h3>
    <ButtonAutn type={'add'} btnName={'add'}/>
    <ButtonAutn type={'delete'} btnName={'delete'}/>
    <ButtonAutn type={'edit'} btnName={'edit'}/>
    <ButtonAutn type={'select'} btnName={'select'}/>
</div>
转载自:https://juejin.cn/post/7367554378733305892
评论
请登录