Маршрутизация разрешений Vue [управление разрешениями меню/кнопками]

Vue.js

предисловие

Я прошел систему управления фоном железной дороги в течение полугода.Общий бизнес системы относительно сложный.Это также полная системная практика от 0 до 1, когда я пришел в компанию.Я прошел много ям и изучил много в процессе создания этой системы.

Вскоре после завершения этой системы пришла другая система, и я не успел ее обобщить, мне стыдно! На самом деле, большинство основных структур системы управления фоном, которые мы делаем, одинаковы. 角色权限管理, 按钮权限管理и 菜单管理, другие предприятия в основном расширяются на этой основе и, наконец, составляют 符合业务的后台管理系统.

Поскольку все наши проекты используют Vueстек технологий, то эта статья также является объяснением Vue 如何进行权限管理Объяснять.

В конце есть пасхалки!

Разрешение авторизация логин

Любая фоновая система управления начинается с входа в систему и возвращает основную информацию о пользователе и токен после входа в систему.

  • token: депозитsessionStronge / localStronge, а затем добавляется в упакованныйAxiosВ заголовке запроса каждый запрос содержит токен.
  • Основная информация о пользователе

После успешного входа в систему одновременно можно сделать много дел, и конкретный бизнес рассматривается подробно.后台管理系统После успешного входа в систему будет запрошен интерфейс разрешений меню текущего пользователя для получения доступных маршрутов пользователя (динамических маршрутов). Vue RouterЕго нельзя использовать напрямую, его необходимо разобрать на Vue Router 可识别的格式 .

Авторизоваться

    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true;
          login(this.loginForm)
            .then(res => {
              if (res.code === 200) {
                // 存放token
                sessionStorage.setItem("tokens", res.data.token);
                // 触发Vuex 来 加载 获取当前用户的菜单,并解析路由
                store.dispatch("setMenuList");
                this.$message({
                  message: "登录成功",
                  type: "success",
                  duration: 1000
                });
                this.$router.replace({ path: "/dashboard" });
              }
            })
            .catch(() => {
              this.loading = false;
            });
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    }

Получить текущее меню пользователя и проанализировать маршрут

После успешного входа эта статья проходит Vuexчтобы получить текущее меню пользователя и разрешить маршрут.

store.dispatch("setMenuList");

/*
 * @Description: 
 * @Author: ZhangXin
 * @Date: 2021-02-02 16:10:59
 * @LastEditTime: 2021-02-23 23:03:30
 * @LastEditors: ZhangXin
 */
// getMenu 解析后台路由
import { getMenu } from '../../utils/getMenu'
// 引入路由 和 静态路由
import router, { constantRoutes } from '../../router/index'
const state = {
  routerType: '',
  // 菜单路由
  meunList: []
}

const mutations = {
  SET_ROUTER_TYPE(state, type) {
    state.routerType = type
  },
  SET_ROUTER_MENULIST(state, list) {
    // 静态路由 +  动态路由  合并  完整路由
    const array = constantRoutes.concat(list)
    state.meunList = array
    router.options.routes = array
    router.addRoutes([...array])
  }
}

const actions = {
  setMenuList({ commit, state }) {
    // 接收返回来的 路由数组
    return new Promise((resolve, reject) => {
      getMenu().then(res => {
        commit('SET_ROUTER_TYPE', '')
        commit('SET_ROUTER_MENULIST', res)
        resolve(res)
      })
    })
  }
}
export default {
  state,
  mutations,
  actions
}

Разобрать бэкенд, чтобы вернуться к маршруту (выделено)

Маршрут, возвращаемый инкапсулированным сервером синтаксического анализа, в основном предназначен для Vuexиспользуется в.

/*
 * @Description: 
 * @Author: ZhangXin
 * @Date: 2021-02-02 16:03:48
 * @LastEditTime: 2021-02-23 23:09:02
 * @LastEditors: ZhangXin
 */
import Layout from '@/layout'
import {getUserAuthMenu} from '@/api/user'



/**
 * @description: 解析后端返回来的菜单树
 * @param {*} data 后端返回来的路由树
 * @param {*} arr 菜单
 * @return {*}
 */
function tree(data, arr) {
  data.forEach((datas, index) => {
    arr.push({
      path: datas.path,
      name: datas.name,
      types: datas.types,
      hidden: datas.hidden == 'true' ? true : false,
      // 当时这块踩坑了
      component: datas.component === 'Layout' ? Layout : resolve => require([`@/views/${datas.component}.vue`], resolve),
      meta: {
        title: datas.meta.title,
        icon: datas.meta.icon,
        // 用来存放按钮权限
        button: datas.meta.button
      },
      //  redirect: datas.redirect,
      id: datas.id,
      // 子路由
      children: []
    })

    if (datas.children) {
      const childArr = tree(datas.children, [])
      arr[index].children = childArr
    }
  })
  return arr
}


/**
 * @description: 获取当前登录用户的菜单
 * @param {*}
 * @return {*}
 */
export function getMenu() {
  return new Promise(function (resolve, reject) {
    getUserAuthMenu().then(res => {
      if(res.code === 200){
      const datas = res.data
      // 调用 tree 来解析后端返回来的树
      resolve(tree(datas, []))
      }

    })
  })
}

Бэкэнд получает формат маршрутизации

Реальное дерево меню, полученное фронтендом

Обновление страницы, маршрутизация потеряна

До сих пор было достигнуто Vue 动态权限控制, не радуйтесь, ха-ха, как только страница обновится, страница войдет404 页面.

Почему это ?

из-за депозита VuexДанные на странице будут очищены, как только страница будет обновлена, поэтому, конечно, если текущий маршрут не может быть найден, введите 404 页面了 .

Как с этим бороться?

**1. Полный маршрут, состоящий из статики и динамики, можно сохранить в sessionStronge / localStronge, а затем, когда страница обновится, передать файл глобальной записиApp.vueЖизненный цикл созданного , будетrouter = sessionStronge / localStrongeПолный маршрут сохраняется, и при обновлении страницы он перезагружается. **

2. Если вы используетеVuexчтобы получить и проанализировать меню пользователя, затем вы можете ввести его в файл глобальной записиApp.vueЖизненный цикл созданного, выполнить сноваVuex Actionчтобы перезагрузить меню пользователя

я прямо вApp.vueжизненный циклcreated, выполненный снова Vuexдля загрузки и анализа, больше ничего. Конечно, это зависит от конкретного бизнеса.

<template>
  <div id="app">
    <router-view v-if="isRouterAlive" />
  </div>
</template>

<script>
import store from "@/store";
export default {
  name: "App",
  provide() {
    return {
      reload: this.reload
    };
  },
  data() {
    return {
      isRouterAlive: true
    };
  },
  methods: {
    reload() {
      this.isRouterAlive = false;
      this.$nextTick(() => (this.isRouterAlive = true));
    }
  },
  created() {
      //只要刷新页面,就会重新加载路由树,保证了路由不会丢失数据
	  store.dispatch("setMenuList");
  }
};
</script>

Суммировать

смысл

  • 1. Определение соответствует текущему формату бизнес-маршрутизации проекта, а клиентская и серверная часть принимаются и доставляются в соответствии с этим
  • 2. Интерфейсная часть анализирует динамический маршрут, возвращаемый серверной частью, и генерируетVue RouterУзнаваемый формат и, наконец, сращивание, полная маршрутизация
  • 3. Обновить обработку потери маршрута

кнопка управления доступом

  • 1. Текущий маршрут компонента содержит доступные разрешения кнопок, сохраняет их в массиве и оценивает, отображается ли он с помощью v-if
  • 2. При входе получить права кнопок всей системы по отдельности, все полученные кнопки сохранить в массив, выложить в глобал, а потом с помощью v-if определить, отображать ли
  • **3. ............ **