首页 > 其他分享 >VueRouter 实现登录后跳转到之前相要访问的页面的简单示例

VueRouter 实现登录后跳转到之前相要访问的页面的简单示例

时间:2022-10-25 17:33:05浏览次数:45  
标签:redirect 登录 示例 相要 params routePaths 跳转 query 路由

简介

该功能主要用于判定用户权限,在用户无权限时重定向至登录页,并在用户完成登录后,再定向至用户之前想要访问的路由;或者用户在任意路由点击登录时,登录成功后返回当前路由。是一个很常规的小功能。

简单示例

本文仅演示路由跳转和导航守卫相关代码的实现,不包含具体的权限验证和登录请求。

实现该功能主要分为四步:

  • 在登录组件的路由配置对象中添加 props: route => ({ redirect: route.query.redirect })

  • 在登录组件中使用 props 接收参数 props: ['redirect'] ,同时在登录事件完成时判定路由参数并跳转:

    props: ['redirect'],
    ...
    handleLogin() {
      this.$store.dispatch('LOGIN', { somePramsHere })
        .then(() => {
          this.$router.push(
            this.redirect ? { path: this.redirect } : { name: 'Home' }
          );
        })
        .catch((err) => {
          // 登录失败
        });
    },
    
  • 在其他路由的登录入口添加相应的 rediect 参数,如首页的登录链接:

    <router-link 
      :to="{
             name: 'Login',
             query: { redirect: $route.fullPath },
           }"
     ><span class="login">登录</span></router-link>
    
  • 在路由守卫中添加相应的判定逻辑,当用户不具备权限时,重定向至登录页:

    import router from './index';
    import store from '@/store/index';
    import whiteList from './whiteList';
    
    router.beforeEach((to, from, next) => {
        if (!store.state.token) {
            // 未登录
            if (
                to.matched.length > 0 &&
                to.matched.some((record) => whiteList.includes(record.path))
                // 此处还可添加用户权限验证相关逻辑,如 to.matched.some(record => record.requiresAuth)
            ) {
                // 该路由不要求用户登录,继续完成导航
                next();
            } else {
                // 用户未登录,且目标路由不在白名单中,重定向至登录页
                next({ name: 'Login', query: { redirect: to.fullPath } });
            }
        else { ... // 已登录时的路由守卫判定 }
        }
    }
    

补充用户退出时的处理

由于导航守卫只有在路由变化时才会被触发,而使用 $router.replace() 模拟刷新并不会触发导航守卫(push() 也不行),因为 VueRouter 不允许进入相同的路由,这是其内部机制,我们无法在外部干涉。

因此,只能在用户退出成功时,手动加入与导航守卫相同的判定逻辑,若在白名单之内或拥有相应的路由权限,则留在当前路由;若不符合条件,则重定向至登录页:

退出相关组件

import whiteList from '@/store/whiteList';
import routePaths from '@/store/routePaths';

...
handleLogoutRedirect() {
  let location = {};
  if (
    !whiteList.includes(this.routePath) &&
    !whiteList.includes(routePaths[this.routeName])
  ) {
    location = { name: 'Login', query: { redirect: this.routePath } }; // 注意这里,需要手动带上当前路径,否则重新登录后只能到首页
    this.$router.push(location);
  }
  // 当前路由在白名单之内的,不需要跳转,留在当前路由即可
},
handleLogout() {
  this.$store
    .dispatch('LOGOUT')
    .then(() => {
      this.handleLogoutRedirect();
    })
    .catch((err) => err);
},
...

注意,我在顶部导入了一个 routePaths 对象。由于搜索页等组件是带有 params 参数的,若想要判定当前路由是否属于白名单,需要使用路由配置对象中的完整 path 字符串,比如搜索页是 /search/:keyword?,那么白名单数组和 routePaths 对象里都需要使用这个字符串。此处为了匹配的方便,使用路由组件的 name 属性作为 routePaths 的 key。示例:

routePaths.js

// 其他路由若是 path 不带 params 参数的,可以不用配置,像上述代码那样分开判定即可
const routePaths = {
    Search: '/search/:keyword?',
}
export default routePaths;

进阶

在任意路由点击登录,将当前路由和路由参数都带给登录组件,登录成功后返回之前的路由并携带全部路由参数。

此处的导航守卫、以及带有登录链接或跳转至登录页功能的组件代码无需改动,只需要修改路由配置对象和登录组件。

首先,定义路由的配置对象时,将登录组件的路由 props 改为:

props: route => {
  let params = route.params, query = route.query; // 这里不能解构 route 对象,否则拿不到值
  const redirect = query.redirect;
  Reflect.deleteProperty(query, 'redirect'); // 原本的 query 对象不带 redirect 属性,因此需要删除
  return { redirect, params, query }
},

其次,登录成功时,给路由跳转添加 prams 和 query 参数

props: ['redirect', 'params', 'query'],
...
handleLogin() {
  this.$store
    .dispatch('LOGIN', { phone: this.phone, password: this.password })
    .then((data) => {
      this.$router.push(
        this.redirect
          ? { path: this.redirect, params: this.params, query: this.query }
          : { name: 'Home' }
      );
    })
    .catch((err) => {
      console.log('登录失败:', err);
    });
},

标签:redirect,登录,示例,相要,params,routePaths,跳转,query,路由
From: https://www.cnblogs.com/cjc-0313/p/16825651.html

相关文章