网站建设网站建设哪里有,沈阳网站seo排名优化,网站推广上首页,网站空间哪里买文章目录 一、获取权限码二、三种按钮级别的权限控制方式【1】函数方式【2】组件方式【3】指令方式 一、获取权限码 要做权限控制#xff0c;肯定需要一个code#xff0c;无论是权限码还是角色码都可以#xff0c;一般后端会一次性返回#xff0c;然后全局存储起来就可以了… 文章目录 一、获取权限码二、三种按钮级别的权限控制方式【1】函数方式【2】组件方式【3】指令方式 一、获取权限码 要做权限控制肯定需要一个code无论是权限码还是角色码都可以一般后端会一次性返回然后全局存储起来就可以了在登录成功以后获取并保存到全局的store中 import { defineStore } from pinia;
export const usePermissionStore defineStore({state: () ({// 权限代码列表permCodeList: [],}),getters: {// 获取getPermCodeList(){return this.permCodeList;}, },actions: {// 存储setPermCodeList(codeList) {this.permCodeList codeList;},// 请求权限码async changePermissionCode() {const codeList await getPermCode();this.setPermCodeList(codeList);}}
})二、三种按钮级别的权限控制方式
【1】函数方式
使用示例如下
templatea-button v-ifhasPermission([20000, 2000010]) colorerror classmx-4拥有[20000,2000010]code可见/a-button
/templatescript langtsimport { usePermission } from //hooks/web/usePermission;export default defineComponent({setup() {const { hasPermission } usePermission();return { hasPermission };},});
/script本质上就是通过v-if只不过是通过一个统一的权限判断方法hasPermission export function usePermission() {function hasPermission(value, def true) {// 默认视为有权限if (!value) {return def;}const allCodeList permissionStore.getPermCodeList;if (!isArray(value)) {return allCodeList.includes(value);}// intersection是lodash提供的一个方法用于返回一个所有给定数组都存在的元素组成的数组return (intersection(value, allCodeList)).length 0;return true;}
}很简单从全局store中获取当前用户的权限码列表然后判断其中是否存在当前按钮需要的权限码如果有多个权限码只要满足其中一个就可以。 【2】组件方式 除了通过函数方式使用也可以使用组件方式Vue vben admin提供了一个Authority组件使用示例如下 templatedivAuthority :valueRoleEnum.ADMINa-button typeprimary block 只有admin角色可见 /a-button/Authority/div
/template
scriptimport { Authority } from //components/Authority;import { defineComponent } from vue;export default defineComponent({components: { Authority },});
/script使用Authority包裹需要权限控制的按钮即可该按钮需要的权限码通过value属性传入接下来看看Authority组件的实现。 script langtsimport { defineComponent } from vue;import { usePermission } from //hooks/web/usePermission;import { getSlot } from //utils/helper/tsxHelper;export default defineComponent({name: Authority,props: {value: {type: [Number, Array, String],default: ,},},setup(props, { slots }) {const { hasPermission } usePermission();function renderAuth() {const { value } props;if (!value) {return getSlot(slots);}return hasPermission(value) ? getSlot(slots) : null;}return () {return renderAuth();};},});
/script同样还是使用hasPermission方法如果当前用户存在按钮需要的权限码时就原封不动渲染Authority包裹的内容否则就啥也不渲染。 【3】指令方式
使用示例如下
a-button v-auth1000 typeprimary classmx-4 拥有code [1000]权限可见 /a-button实现如下
import { usePermission } from //hooks/web/usePermission;function isAuth(el, binding) {const { hasPermission } usePermission();const value binding.value;if (!value) return;if (!hasPermission(value)) {el.parentNode?.removeChild(el);}
}const mounted (el, binding) {isAuth(el, binding);
};const authDirective {// 在绑定元素的父组件// 及他自己的所有子节点都挂载完成后调用mounted,
};// 注册全局指令
export function setupPermissionDirective(app) {app.directive(auth, authDirective);
}只定义了一个mounted钩子也就是在绑定元素挂载后调用依旧是使用hasPermission方法判断当前用户是否存在通过指令插入的按钮需要的权限码如果不存在直接移除绑定的元素。 很明显权限控制的实现有两个问题一是不能动态更改按钮的权限二是动态更改当前用户的权限也不会生效。 【1】解决第一个问题很简单因为上述只有删除元素的逻辑没有加回来的逻辑那么增加一个updated钩子 app.directive(auth, {mounted: (el, binding) {const value binding.valueif (!value) returnif (!hasPermission(value)) {// 挂载的时候没有权限把元素删除removeEl(el)}},updated(el, binding) {// 按钮权限码没有变化不做处理if (binding.value binding.oldValue) return// 判断用户本次和上次权限状态是否一样一样也不用做处理let oldHasPermission hasPermission(binding.oldValue)let newHasPermission hasPermission(binding.value)if (oldHasPermission newHasPermission) return// 如果变成有权限那么把元素添加回来if (newHasPermission) {addEl(el)} else {// 如果变成没有权限则把元素删除removeEl(el)}},
})const hasPermission (value) {return [1, 2, 3].includes(value)
}const removeEl (el) {// 在绑定元素上存储父级元素el._parentNode el.parentNode// 在绑定元素上存储一个注释节点el._placeholderNode document.createComment(auth)// 使用注释节点来占位el.parentNode?.replaceChild(el._placeholderNode, el)
}const addEl (el) {// 替换掉给自己占位的注释节点el._parentNode?.replaceChild(el, el._placeholderNode)
}主要就是要把父节点保存起来不然想再添加回去的时候获取不到原来的父节点另外删除的时候创建一个注释节点给自己占位这样下次想要回去能知道自己原来在哪。 【2】第二个问题的原因是修改了用户权限数据但是不会触发按钮的重新渲染那么我们就需要想办法能让它触发这个可以使用watchEffect方法我们可以在updated钩子里通过这个方法将用户权限数据和按钮的更新方法关联起来这样当用户权限数据改变了可以自动触发按钮的重新渲染 import { createApp, reactive, watchEffect } from vue
const codeList reactive([1, 2, 3])const hasPermission (value) {return codeList.includes(value)
}app.directive(auth, {updated(el, binding) {let update () {let valueNotChange binding.value binding.oldValuelet oldHasPermission hasPermission(binding.oldValue)let newHasPermission hasPermission(binding.value)let permissionNotChange oldHasPermission newHasPermissionif (valueNotChange permissionNotChange) returnif (newHasPermission) {addEl(el)} else {removeEl(el)}};if (el._watchEffect) {update()} else {el._watchEffect watchEffect(() {update()})}},
})将updated钩子里更新的逻辑提取成一个update方法然后第一次更新在watchEffect中执行这样用户权限的响应式数据就可以和update方法关联起来后续用户权限数据改变了可以自动触发update方法的重新运行。