前言

  • 讲解权限相关的功能:不同用户登录的侧边栏的菜单是不一样的。
  • 简单来讲大致需要满足的功能就是:
    1. 不同的用户会根据权限不同,在后台管理系统渲染不同的菜单栏。
    2. 用户登陆之后,会获取路由菜单和一个token,之后跳转的页面都需要带着token。
    3. 用户退出登陆,清除动态路由,清除token。跳转到login页面。
    4. 如果当前没有token,那么跳转到任何页面都应该重定向到login页面。

登陆操作

  • 登陆操作应该至少要做三件事情

    1. 获取当前用户对应的菜单栏的菜单,并存储到vuex和cookies中。
    2. 获取当前用户的Token,存储到vuex和cookie中
    3. 获取当前的菜单生成动态路由。
  • 登录页面代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    methods: {
    login() {
    this.$http.post('api/permission/getMenu', this.form).then(res => {
    res = res.data
    if (res.code === 20000) {
    //先清除 房子重复加入
    this.$store.commit('clearMenu')
    //再加入
    this.$store.commit('setMenu', res.data.menu)
    //放入token
    this.$store.commit('setToken', res.data.token)
    //添加动态路由
    this.$store.commit('addMenu', this.$router)
    //跳转到首页
    this.$router.push({ name: 'home' })
    } else {
    //如果失败 提示失败信息
    this.$message.warning(res.data.message)
    }
    })
    }
    }

退出登陆操作

  • 退出登陆所做的事情就和登陆相反,主要做两件事情

    1. 清除 vuex 和 cookie 中的菜单
    2. 清除 vuex 和 cookie 中的 token
  • 退出登录的代码

    1
    2
    3
    4
    5
    6
    7
    8
    logOut() {
    //清除token
    this.$store.commit('clearToken')
    //清除菜单
    this.$store.commit('clearMenu')
    //重定向 一般是登陆页
    location.reload()
    }

路由守卫

  • 因为是后台管理系统, 所以在我们在每切换一个路由都需要判断当前token是否存在, 这个时候就需要通过路由守卫来实现。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // main.js

    import router from "./router"; //引入 vue-router
    router.beforeEach((to, from, next) => {
    // 防止刷新后vuex里丢失token
    store.commit("getToken");
    // 防止刷新后vuex里丢失标签列表tagList
    store.commit("getMenu");
    let token = store.state.user.token;
    // 过滤登录页,因为去登陆页不需要token(防止死循环)
    if (!token && to.name !== "login") {
    next({ name: "login" });
    } else {
    // 有 Token 放行
    next();
    }
    });

VUEX的操作

  • vuex存放token相关方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import Cookie from "js-cookie";
    export default {
    state: {
    token: "",
    },
    mutations: {
    //存放token
    setToken(state, val) {
    state.token = val;
    Cookie.set("token", val);
    },
    //清空token
    clearToken(state) {
    state.token = "";
    Cookie.remove("token");
    },
    //获取token
    getToken(state) {
    state.token = Cookie.get("token");
    },
    },
    actions: {},
    };
  • vuex存放菜单相关方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    import Cookie from "js-cookie";
    export default {
    state: {
    menu: [],
    },
    mutations: {
    setMenu(state, val) {
    //vuex添加
    state.menu = val;
    //cookie也添加
    Cookie.set("menu", JSON.stringify(val));
    },
    clearMenu(state) {
    //清除也一样 vuex和cookie都清除
    state.menu = [];
    Cookie.remove("menu");
    },
    addMenu(state, router) {
    if (!Cookie.get("menu")) {
    return;
    }
    //取出cookie数据 给vuex
    let menu = JSON.parse(Cookie.get("menu"));
    state.menu = menu;
    //添加动态路由 主路由为Main.vue
    let currentMenu = [
    {
    path: "/",
    component: () => import(`@/views/Main`),
    children: [],
    },
    ];
    //如果是一级菜单 那么菜单名称肯定有路由 如果是二级菜单那么一级没有 二级有路由
    menu.forEach((item) => {
    if (item.children) {
    item.children = item.children.map((item) => {
    item.component = () => import(`@/views/${item.url}`);
    return item;
    });
    currentMenu[0].children.push(...item.children);
    } else {
    item.component = () => import(`@/views/${item.url}`);
    currentMenu[0].children.push(item);
    }
    });
    //添加动态路由
    router.addRoutes(currentMenu);
    },
    },
    actions: {},
    };
  • 到这里就已经写完了。

优化访问链接

  • 上面的代码默认登录后访问首页,需要改成跳转到原来的链接

  • 在登录页上修改跳转的页面

    1
    2
    this.$router.push(this.$route.query.redirect || "home");
    // this.$router.push({ name: 'home' });
  • 路由守卫中跳转到到登录页面的时候带上访问的目标路径

    1
    2
    3
    4
    5
    6
    7
    8
    // next({ name: 'login' });
    next({
    name: "login",
    query: {
    // 把跳转登录的页面参数传递到login页
    redirect: to.fullPath,
    },
    });