登录的检测方式


1、组件内的检测

检测登录第一种方式,最垃圾,是从组件内部的created方法进行检测,每个需要登录的组件都需要写一遍,很烦

created() {
const openid = localStorage.getItem("openid");
if (!openid) {
  this.$router.push("/login");
}
},
2、使用组件的继承

使用组件的继承,从父组件实现检测登录,当前组件继承父组件,将会自动调用登录检测

父组件:IsLogin.vue

<script>
export default {
  data() {
    //    当前组件会被子组件继承,那么该data内的openid依然也会被继承,则在子组件内可直接使用this.openid来获取登录用户状态
    return { 
      openid: null 
    };
  },
  created() {
    const openid = localStorage.getItem("openid");
    //    将openid赋值到组件数据data内,子组件继承后可直接使用
    this.openid = openid;
    if (!openid) {
      this.$router.push("/login");
    }
  },
};
</script>

子组件:

//    导入父组件
import IsLogin from "@/components/IsLogin";

export default {
  // 组件的继承关系,并不是父子组件的包含关系,而是父子继承后是一体的,父子组件包含关系不是一体的。
  // 组件的继承就像类的继承一样,而父子组件包含并不是继承。
  extends: IsLogin
}
3、路由检测

在路由检测登录状态,但是缺陷很明显,路由会中断跳转,不会进入到组件内部,所以不能实现跳转返回
例如:从A页面跳转到B页面,B页面又需要登录状态,会自动跳转到Login页面,此时Login登录后返回时,将无法获取到B页面的链接
不能实现B页面的登录后跳转返回(原因是根本就没有进入到B页面组件内,在路由处就掐死了)

router/index.js

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

router.beforeEach((to, from, next) => {


    // 不管多少个页面,只要你需要用户登录状态的页面,你要跳转到需要用户登录的页面之前
    // 进行判断,是不是登录了呢?登录的条件源自于:有没有OpenId,如果有的话,那么正常放行
    // 否则呢,你就需要让他先登录

    let paths = [
        '/mine',
        '/order'
    ];

    // paths.includes(to.path)
    // 相当于:
    // if (to.path == '/mine' || to.path == '/order')
    if (paths.includes(to.path)) {
        let openid = localStorage.getItem('openid');
        // 判断有无登录状态,如果有,放行;如果没有,就让用户去登录
        if (openid) {
            next();
        } else {
            // next({ path: '/login' });
            next('/login')
        }
    } else {
        // 如果不是你要检测的URL,那么直接放行
        next();
    }

})
以上三种登录检测的通用页面(路由内守卫)

login.vue

// 获取即将跳转至login页的 链接
// 跳转之login页的上一个页面
// 路由内守卫
beforeRouteEnter(to, from, next) {
  // 我们想要在这里得到上个页面的链接地址,并在登录成功之后,跳转回去。↓
  // 这里的VM指的是,当前组件的this实例
  next((vm) => {
    vm.returnURL = from.path;
  });
},
  methods: {
    onSubmit(values) {
      console.log(this.returnURL);
      axios({
        url: "/login.php",
        method: "GET",
        params: {
          username: values.username,
          password: values.password,
        },
      }).then((res) => {
        let data = res.data;
        if (data.status == false) {
          // Toast("密码错误,请重试");
          Notify({ type: "danger", message: "密码错误,请重试" });
        } else {
          Notify({ type: "success", message: "登录成功" });
          let openid = data.openid;
          localStorage.setItem("openid", openid);

          setTimeout(() => {
            // 这里的returnURL是从当前组件的路由守卫获取的
            this.$router.replace(this.returnURL);
          }, 3000);
        }
      });
    },
  },

登录的过程


1、制作登录页面

需要做好登录页面、并且处理好登录逻辑,包括登录后的返回处理(登录之后需要返回、跳转到登录之前的页面)

2、登录状态的检测

构思哪些页面需要用到登录后的状态,在这些页面内进行登录检测,如果没有登录状态(没登录),那么就让用户去登录页面先登录;

对于登录的检测,我们推荐使用第二种方式:父子继承判断登录状态,获取登录信息。

3、根据令牌获取用户数据

已经有登录的令牌了,根据令牌,去获取用户的数据(拿登录的令牌去获取已登录的用户信息和已登录的用户数据)

登录后的跳转


因为登录成功之后需要跳转到登录前的页面,所以我们需要在登录页面获取到从哪里跳转来的链接,然后返回回去。
路由内的守卫就可以获取到登录前的页面,我们先将该链接保存到组件实例内的data:

第一种方式:
// 获取即将跳转至login页的 链接
// 跳转之login页的上一个页面
// 路由内守卫
beforeRouteEnter(to, from, next) {
  // 我们想要在这里得到上个页面的链接地址,并在登录成功之后,跳转回去。↓
  // 这里的VM指的是,当前组件的this实例
  next((vm) => {
    vm.returnURL = from.path;
    //    跳转回去的路径,有可能带query参数如:/order?id=1111,如果你不处理query,那么直接根据path跳转回去是:/order而不是/order?id=1111,所以我们需要加入query
    //    第一种方式,可以记录from.query
    vm.returnQuery = from.query;
  });
},

当登录成功后,可以根据组件实例this内的data保存的链接地址,进行返回。返回该链接时:

setTimeout(() => {
  // 这里的returnURL是从当前组件的路由守卫获取的
  this.$router.replace({ path: this.returnURL, query:this.returnQuery });
}, 3000);
第二种方式:

beforeRouteEnter(to, from, next) {
  next((vm) => {
    //    跳转回去的路径,有可能带query参数如:/order?id=1111,如果你不处理query,那么直接根据path跳转回去是:/order而不是/order?id=1111,所以我们需要加入query
    
    //    第二种方式,直接使用fullPath,就不用写path和query了
    vm.returnURL = from.fullPath;
  });
},
    

返回链接:

setTimeout(() => {
  // 这里的returnURL是从当前组件的路由守卫获取的
  this.$router.replace(this.returnURL);
}, 3000);

推荐使用第二种方式

添加新评论