前端框架对比系列之vue和react的按钮权限控制(一)
前言
- 如果系统角色是固定的,我们可以将按钮权限类似角色一样配置在
routes
里面; - 通过动态添加路由的方法,即调用后端接口返回当前用户角色拥有的所有页面菜单信息,将菜单格式化成路由之后,再动态的添加到前端系统中,这种方式会更加灵活。
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
,在自定义指令中通过在bind
和update
方法中获取传入的参数实现当前绑定的按钮的显示和隐藏。页面中的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
,在自定义指令中通过在bind
和update
方法中获取传入的参数实现当前绑定的按钮的显示和隐藏。页面中的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