Web前端登录的检测方式
登录的检测方式
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);
推荐使用第二种方式