面试官问我按钮级别权限怎么控制,我说v-if,面试官说再见,前端开发必看

44 阅读3分钟
    async changePermissionCode() {
        const codeList = await getPermCode();
        this.setPermCodeList(codeList);
    }
}

})


接下来它提供了三种按钮级别的权限控制方式,一一来看。



## 函数方式


使用示例如下:




本质上就是通过`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`中获取当前用户的权限码列表,然后判断其中是否存在当前按钮需要的权限码,如果有多个权限码,只要满足其中一个就可以。


## 组件方式


除了通过函数方式使用,也可以使用组件方式,`Vue vben admin`提供了一个`Authority`组件,使用示例如下:




使用`Authority`包裹需要权限控制的按钮即可,该按钮需要的权限码通过`value`属性传入,接下来看看`Authority`组件的实现。




同样还是使用`hasPermission`方法,如果当前用户存在按钮需要的权限码时就原封不动渲染`Authority`包裹的内容,否则就啥也不渲染。


## 指令方式


最后一种就是指令方式,使用示例如下:



拥有code ['1000']权限可见


实现如下:



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`方法,判断当前用户是否存在通过指令插入的按钮需要的权限码,如果不存在,直接移除绑定的元素。


很明显,`Vue vben admin`的实现有两个问题,一是不能动态更改按钮的权限,二是动态更改当前用户的权限也不会生效。


解决第一个问题很简单,因为上述只有删除元素的逻辑,没有加回来的逻辑,那么增加一个`updated`钩子:



app.directive("auth", { mounted: (el, binding) => { const value = binding.value if (!value) return if (!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) }

最后

四轮技术面+一轮hr面结束,学习到了不少,面试也是一个学习检测自己的过程,面试前大概复习了 一周的时间,把以前的代码看了一下,字节跳动比较注重算法,面试前刷了下leetcode和剑指offer, 也刷了些在牛客网上的面经。大概就说这些了,写代码去了~

祝大家都能收获大厂offer~

篇幅有限,仅展示部分内容

开源分享:docs.qq.com/doc/DSmRnRG…