前端菜单及按钮权限拦截,实现方案及思路

简介: 此实现方案基于vue框架,并需要依赖vue项目相关的库,router、store等等;前端同学要与后端同学协商,常规是让后端返回一个树结构的菜单数据,并且将所有的涉及权限控制的页面path给到后端,如果是按钮,需要把所有的按钮 code 码统一下,这是前期工作,很重要。

【前言】

此实现方案基于vue框架,并需要依赖vue项目相关的库,router、store等等;前端同学要与后端同学协商,常规是让后端返回一个树结构的菜单数据,并且将所有的涉及权限控制的页面path给到后端,如果是按钮,需要把所有的按钮 code 码统一下,这是前期工作,很重要。

首先,main.js 引入相关文件

import Vue from 'vue';
import App from './App.vue';
import router from '@/router';
import store from '@/store';
import '@/plugins/permission';
import '@/plugins/directives';
import '@/plugins/auth';

Vue.config.productionTip = false;

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

在main.js 同目录创建 plugins 文件,作为公共文件,在plugins 里创建 permission.js

import router from @/router';
import store from '@/store';
import { hasMenuAuth } from '@/plugins/auth';


router.beforeEach(async (to, from, next) => {
    store.dispatch('auth/getAuthData');
  // 校验菜单权限
      if (hasMenuAuth(to.path)) {
        next();
      } else {
        next({ path: '/' });
      }
});

在store目录里创建 auth.js ,getUserMenuList 为定义的接口 api

import { getUserMemuList } from @/api/auth';

/**
 * 树型数据转列表
 * @param {*} tree 树型数据
 * @param {*} childrenKey 子节点列表键
 */
const convertTreeToList = (tree, childrenKey = 'children') => {
  if (!Array.isArray(tree)) return [];
  // 所有的菜单集合
  let list = [];
  // 递归查找
  let fn = data => {
    let origin = data.slice(0);
    list = list.concat(origin);
    data.forEach(item => {
      let children = item[childrenKey];
      Array.isArray(children) && fn(children);
    });
  };
  fn(tree);
  return list;
};

const state = {
  // 路由菜单权限
  routeAuthList: {},
  // 按钮权限列表
  authList: {}
  }
};

const mutations = {
   // 菜单权限列表
  SET_ROUTE_AUTH_LIST(state, data) {
    // 路由权限集合
    let routeAuthList = {};
    // 按钮权限集合
    let buttonAuthList = {};
    data.map(item => {
      // 将所有的 path 存入对象中
      if (item.path) {
        routeAuthList[item.path] = true;
      }
      // 将所有的 code 存入对象中
      if (item.code) {
        buttonAuthList[item.code] = true;
      }
    });
    state.routeAuthList = routeAuthList;
    state.authList = buttonAuthList;
  },
};

const actions = {
  // 获取菜单列表
  getAuthData({ commit }) {
    return getUserMemuList().then(({ data }) => {
      let list = convertTreeToList(data);
      commit('SET_ROUTE_AUTH_LIST', list);
      return data;
    });
  },
};

export default {
  namespaced: true,
  state,
  mutations,
  actions
};

这时,例如在页面中打印,效果是这样的

前端菜单-1.png

1.png

前端菜单-3.png

至此,已经将该用户下所属的权限拉取,并存储在 store 里了,可以全局访问使用。

前面 permission 文件里引用的 hasMenuAuth 方法,需要在 plugins 目录中,创建 auth.js, 并定义下此方法。

import Vue from 'vue';
import store from '@/store';

/**
 * 校验路由是否有权限
 * @param {Array} path 权限
 * @return {boolean}
 */
export function hasMenuAuth(path) {
  // 无权限配置无需校验
  if (!(path && path.length)) return true;
  const list = store.state.auth.routeAuthList;
  // 校验是否有权限
  let auth = list[path] ? true : false;
  return auth;
}

/**
 * 校验按钮是否有权限
 * @param {*} list 权限配置
 */
export function hasBtnAuth(list) {
  // 无权限配置,不校验
  if (!list || !list.length) return true;
  const authList = (store.getters && store.getters.authList) || {};
  let hasPermission = false;
  // // 遍历数组,如果有一个code码存在,则返回true
  list.map(item => {
    if (authList[item]) hasPermission = true;
  });
  return hasPermission;
}

// 挂在权限校验方法
Vue.has = hasBtnAuth;
Vue.prototype.$has = hasBtnAuth;

到此处,整个项目路由的拦截就实现了,但目前只拦截了 path,但有页面的按钮,虽然点击后由于做了拦截,让其跳到了默认页。但按钮的还是展示的,这时就需要用到 上面的 hasBtnAuth 方法了。

由于已经在vue实例上挂载了 $has,只需在 vue 组件中使用就好了,可以用在节点里,也可在方法里。

前端菜单-4.png

前端菜单-5.png

当然按钮的显隐,还有进阶版方法,那就是可以注册个自定义指令,在 plugins 目录下创建 directives.js 文件

/**
 * 按钮权限指令
 * 根据vuex下的auth模块的authList按钮code列表判断权限
 */
import Vue from 'vue';
import store from '@/store';

/**
 * 校验是否有权限,无权限删除dom节点
 * @param {*} el dom元素
 * @param {*} binding 绑定数据
 */
function hasAuth(el, binding) {
  const { value } = binding;
  const authList = (store.getters && store.getters.authList) || [];
  if (value && value instanceof Array && value.length > 0) {
    const list = value;
    let hasPermission = false;
    // 遍历数组,如果有一个code码存在,则返回true
    list.map(item => {
      if (authList[item]) hasPermission = true;
    });
    if (!hasPermission && value && value.length) {
      el.parentNode && el.parentNode.removeChild(el);
    }
  }
}

let auth = {
  inserted: hasAuth,
  update: hasAuth
};

const install = function(Vue) {
  Vue.directive('auth', auth);
};

Vue.use(install);

现在,使用起来更方便了

前端菜单-6.png

好了,具体实现方法就是这些,有些地方简述了,但几乎涉及的地方都涉及到了,欢迎指出不足,我也会补全。

相关文章
|
1月前
|
前端开发 数据可视化 搜索推荐
深入剖析极态云优雅的前端框架设计方案(上)
最近在体验极态云,这款低代码软件开发产品,发现其前端框架设计方案很优雅很强大! 在接下来的学习过程中,我将持续输出自己对极态云前端框架设计方案的深入理解,包括具体的使用技巧、优势分析以及可能的应用场景等方面的内容,希望能为大家提供有价值的参考。
|
3月前
|
前端开发 数据安全/隐私保护
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
本文档详细介绍了HTML表单的多种元素及其用法,包括下拉菜单(`<select>` 和 `<option>`)、文本域(`<textarea>`)、标签解释(`<label>`)、各类按钮(`<button>`)及表单重置功能、无语义布局标签(`<div>` 和 `<span>`)以及字符实体的应用。此外,还提供了一个完整的注册信息表单案例,涵盖个人信息、教育经历和工作经历等部分,展示了如何综合运用上述元素构建实用的表单。
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
|
2月前
|
前端开发 安全 API
前端全栈之路Deno篇(三):一次性搞懂和学会用Deno 2.0 的权限系统详解和多种权限配置权限声明方式
本文深入解析了 Deno 2.0 的权限系统,涵盖主包和第三方包的权限控制机制,探讨了通过命令行参数、权限 API 和配置文件等多种权限授予方式,并提供了代码示例和运行指导,帮助开发者有效管理权限,提升应用安全性。
|
2月前
|
缓存 前端开发 UED
前端 8 种图片加载优化方案梳理
本文首发于微信公众号“前端徐徐”,详细探讨了现代网页设计中图片加载速度优化的重要性及方法。内容涵盖图片格式选择(如JPEG、PNG、WebP等)、图片压缩技术、响应式图片、延迟加载、CDN使用、缓存控制、图像裁剪与缩放、Base64编码等前端图片优化策略,旨在帮助开发者提升网页性能和用户体验。
305 0
|
2月前
|
前端开发
前端如何制作简易的菜单多级导航栏
前端如何制作简易的菜单多级导航栏
70 0
|
3月前
|
Web App开发 前端开发 JavaScript
Web前端项目的跨平台桌面客户端打包方案之——CEF框架
Chromium Embedded Framework (CEF) 是一个基于 Google Chromium 项目的开源 Web 浏览器控件,旨在为第三方应用提供嵌入式浏览器支持。CEF 隔离了底层 Chromium 和 Blink 的复杂性,提供了稳定的产品级 API。它支持 Windows、Linux 和 Mac 平台,不仅限于 C/C++ 接口,还支持多种语言。CEF 功能强大,性能优异,广泛应用于桌面端开发,如 QQ、微信、网易云音乐等。CEF 开源且采用 BSD 授权,商业友好,装机量已超 1 亿。此外,GitHub 项目 CefDetector 可帮助检测电脑中使用 CEF
434 3
|
4月前
|
前端开发 JavaScript 开发者
前端JS按钮点击事件、跳出弹窗、遮罩的实战示例
本文提供了一个前端JS按钮点击事件、弹出式窗口和遮罩层的实战示例,包括HTML、CSS和JavaScript的具体实现代码,以及功能解析,演示了如何实现按钮点击后触发弹窗显示和遮罩层,并在2秒后自动关闭或点击遮罩层关闭弹窗的效果。
前端JS按钮点击事件、跳出弹窗、遮罩的实战示例
|
4月前
|
缓存 前端开发 JavaScript
前端性能优化方案
【8月更文挑战第15天】前端性能优化方案
40 2
|
3月前
|
编解码 前端开发 JavaScript
前端移动端适配方案
【9月更文挑战第8天】前端移动端适配方案
105 0
|
5月前
|
开发框架 JSON 前端开发
Vue&Element 前端应用开发之菜单和路由的关系
Vue&Element 前端应用开发之菜单和路由的关系