vue项目实战-----登录态管理(路由守卫+vuex+axios)(代码片段)

CodingWithyou..... CodingWithyou.....     2023-03-07     358

关键词:

目的:保存用户登录状态,刷新页面时做到用户状态不变:一刷新就去localStorage中获取token与islogin对vuex中的信息进行更新

1.路由拦截/守卫+token+vuex管理 

逻辑:

1.控制页面跳转

如果下一个页面需要登录,判断用户是否登录/是否有token:登录了且下一个不是登录界面就进入,是登录界面就去home;用户没有登录就去登录页------登录后得到token,将token存到store中以及本地。

如果下一个页面不需要登录,直接进入

2.刷新时保存状态

刷新时store会清零,这时就去缓存中拿token,然后去后台获取用户的信息,并将信息存储到store中

3.控制页面登录退出:登录与退出登录时更新状态中islogin

退出时要清空本地缓存哦

难点:

对于islogin,其值为true表示登录,false表示未登录,存放在localStorage里面,因为localStorage里面只能存字符串,所以存进去的时候需要localStorage.setItem(‘islogin’,JSON.stringify(islogin));将islogin变为String类型,取出来的时候需要将islogin转化为Boolean类型,就比如JSON.parse(localStorage.getItem(‘islogin’))这样。

或者可以直接将true/false保存为字符串进行存储

疑难解答

为什么本地存储了islogin或者token,还要在状态管理中进行管理呢?

islogin登录态的管理,vue不能实时监测localStorage的变化,需要实时监测islogin的变化来在页面显示登录还是已经登录,同时vuex中是只要刷新页面就会实时变化的,因此需要在状态管理中管理。

可以这样理解:本地化的存储只是为了控制刷新时的vuex更新,实际控制状态与检测的是vuex中的变量

最安全的就是在点击退出的时候清除本地缓存

islogin和token是否可以只需要一个,还是两个必须都有吗

严格意义上是需要两者都有的,主要是token;token从前后端的通信中进行传输携带,更加安全的验证

而且当状态为登录且用户信息也存在的时候才能算登录,因为token是一直存在的,登录状态不是。因此islogin为了判断用户是否登录,token可以进行前后端的校验

如何做到刷新页面时用户状态不变

页面刷新时,通过路由守卫判断,然后去本地存储中读取信息进行vuex的同步更新

流程

1.路由的配置path时;在需要守卫的path加上meta属性;用于表示下一个路由是否需要在登录后才能进入。

eg:

path: '/home',component: home,meta:requireAuth:true

2.全局守卫在main.js中设置        白名单中的直接访问,黑名单的需要登录

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

if (to.meta.requireAuth)  // 判断该路由是否需要登录权限
    if(JSON.parse(localStorage.getItem('islogin'))) //判断本地是否存在token
      if(to.path=='/login') 
        next(
              path:'/home'   //或者回到当前的路径,不进行跳转   from.path
             )
      elsenext();
      
    else 
      next(
        path:'/login'
      )
    
  
  else 
    next();
  

路由独享守卫

为防止,不经过某路由就直接 在地址栏输入本路由地址而跳转至 本路由,导致本路由获取不到前面路由的某些数据,所以给本路由加 路由独享守卫。

在每一个路由中加而不是在整体的路由上加beforeEnter及逻辑处理

3.store.js    用于保存与更新当前的状态信息

/store.js中
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store(
  state:
	//是否登录判断
	islogin:''
  ,
  mutations:
    login:(state,n) => 
	//传入登录状态islogin
	let islogin = JSON.parse(n);
	localStorage.setItem('islogin',JSON.stringify(islogin));
	console.log(islogin);
	state.islogin = islogin;
    
  

4.页面中触发登录态的地方     状态变更时更新vuex

//这里是登录
login() 
	let flag = true;
	this.$store.commit('login',flag);
	this.$router.push("/home");
	console.log("登录成功");

//这里是退出登录
exit() 
	let flag = false;
	this.$store.commit('login',flag);
	this.$router.push("/login");
	console.log("退出登录");

当前局限:只是限制了用户访问时路由页面的跳转

2.封装 Axios 请求

目的

  1. 每次请求时需要携带token到后台,进行身份认证;
  2. 项目需要根据响应回来的自定义状态码,决定是否跳转到登陆页面。

流程

1.axios

//axios 进行二次封装
//引入axios
import axios from "axios";
//在当前模块引入store
import store from '@/store';
//引入进度条 和 进度条样式  * 非必须
import nprogress from 'nprogress';
import 'nprogress/nprogress.css';
 
//1.利用axios对象的方法create,去创建一个axios实例
//2.这里requests就是axios,只不过稍微配置一下
const requests = axios.create(
     //配置对象
     //基础路径,发请求的时候,路径中会出现api
     baseURL:"/api",
     //请求超时的时间为5s
     timeout:5000,
 );
// 请求拦截器:在发请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情
requests.interceptors.request.use((config)=>
    if(store.state.detail.uuid_token) 
        config.headers.userTempId = store.state.detail.uuid_token;
    
    //需要携带token带给服务器
    if(store.state.user.token) 
        config.headers.token = store.state.user.token;
    
    //进度条开始
    nprogress.start();
    return config;
);
//相应拦截器
requests.interceptors.response.use((res)=>
    //成功回调
    //进度条结束
    nprogress.done();
    return res.data;
,(error)=>
    //失败回调
    new Promise.reject(new Error('faile'));
    
);
 
 
 
 
export default requests;

2.vuex     store.js

import reqGetCode,reqUserRegister,reqUserLogin,reqUserInfo,reqLogout from '@/api';
import setToken,getToken,removeToken from '@/utils/token'
 
//home模块“小”仓库
 
//state:数据仓库
const state = 
    code:'',
    token:getToken(),
    userInfo:

 
//actions:可以处理自己的业务逻辑,也可以异步
const actions = 
    //获取验证码
    async getCode(commit,phone) 
       let result = await reqGetCode(phone);
    //    console.log(result)
       if(result.code == 200 )
           commit("GETCODE",result.data);
           return "ok";
        else 
           return Promise.reject(new Error('faile'));
       
    ,
    //用户注册
    async userRegister(commit,user)
        let result = await reqUserRegister(user);
        if(result.code == 200 ) 
            return 'ok';
         else 
            return Promise.reject(new Error(result.message));
        
 
    ,
    //登陆业务
    async userLogin(commit,data) 
        let result = await reqUserLogin(data);
        if(result.code == 200)  
            commit('USERLOGIN',result.data.token);
            //持久化存储token
            setToken(result.data.token);
            return 'ok';
         else 
            return Promise.reject(new Error(result.message));
        
    ,
    //获取用户信息
    async getUserInfo(commit) 
        let result = await reqUserInfo();
        if(result.code == 200)  
            commit('GETUSERINFO',result.data);
            return 'ok';
         else 
            return Promise.reject(new Error(result.message));
        
    ,
    //退出登录
    async userLogout(commit) 
        let result = await reqLogout();
        if(result.code == 200) 
            commit('CLEAR');
            return 'ok';
         else 
            return Promise.reject(new Error(result.message));
        
    

 
const mutations = 
    GETCODE(state,code) 
        state.code = code;
    ,
    USERLOGIN(state,token) 
        state.token = token;
    ,
    GETUSERINFO(state,userInfo) 
        state.userInfo = userInfo;
    ,
    //清楚本地用户数据
    CLEAR(state) 
        state.token = '';
        state.userInfo = ;
        removeToken();
    
    

 
 
export default 
    state,
    mutations,
    actions,
    getters,

3.token管理

//存token
export const setToken = (token) => 
    localStorage.setItem('TOKEN',token);

//取token
export const getToken = () => 
    return localStorage.getItem('TOKEN');

//清除token
export const removeToken = () => 
    localStorage.removeItem('TOKEN');

 

4.路由配置界面   或者是main.js

//路由配置文件
import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from './routes';
//使用VueRouter插件
Vue.use(VueRouter);
//引入store 
import store from '@/store';
 
 
//先保存一份VueRouter
let originPush = VueRouter.prototype.push;
let originReplace = VueRouter.prototype.replace;
//重写push|replace
//第一个参数:往哪里跳(传递哪些参数)
/** 
 * call 和 apply 区别
 *  相同点:都可以调用函数一次,都可以篡改函数的上下文一次
 *  不同点:call与app传递参数用逗号隔开,apply方法执行,传递数组
 */
VueRouter.prototype.push = function(location,resolve,reject) 
    if(resolve && reject) 
        originPush.call(this,location,resolve,reject);
     else 
        originPush.call(this,location,()=>,()=>);
    

VueRouter.prototype.replace = function(location,resolve,reject) 
    if(resolve && reject) 
        originReplace.call(this,location,resolve,reject);
     else 
        originReplace.call(this,location,()=>,()=>);
    

 
//配置路由
 let router = new VueRouter(
    //路由配置
    routes,
    scrollBehavior (to,from,savedPosition) 
        return y:0
    
);
 
//理由全局守卫,前置守卫(跳转之前判断)
router.beforeEach(async(to,from,next) => 
    // next();
    //获取token
    let token = store.state.user.token;
    let name = store.state.user.userInfo.name;
    if(token) 
        //用户已经登录
        if(to.path == '/login') 
            next('/home');
        else
            if(name)
                next(); 
             else 
                try
                    await store.dispatch('getUserInfo');
                    next();
                 catch(error) 
                    //清楚token
                    await store.dispatch('userLogout');
                    next('/login');
                
            
        
     else 
        // 用户未登录
        let toPath = to.path;
        if(toPath.indexOf('/trade') != -1 || 
            toPath.indexOf('/pay') != -1 || 
            toPath.indexOf('/pausuccess') != -1 || 
            toPath.indexOf('/center') != -1||
            toPath.indexOf('/Search') != -1||
            toPath.indexOf('/shopcart') != -1
            ) 
            next('/login');
         else 
            next();
        
    
);
 
export default router;

vue项目实战-电商后台管理系统(代码片段)

项目简介:该项目为电商后台的管理系统。设计了登录页面。管理人员需要通过输入正确的用户名和密码才能登录。登陆成功之后进入管理页面:管理页面由五个子模块组成:用户管理,权限管理,商品管理&#... 查看详情

vue项目实战:电商后台管理系统(vue+vuerouter+axios+element)(代码片段)

...控制访问权限退出功能通过axios请求拦截器添加token其它3.项目预览首页用户管理用户列表添加用户权限管理角色列表权限列表商品管理商品列表分类参数商品分类添加商品订单管理数据统计电商后台管理系统1.功能开发模式电商... 查看详情

vue项目权限管理

参考技术A首先,权限管理般需求是两个:权限和按钮权限。前端案会把所有路由信息在前端配置,通过路由守卫要求户登录,户登录后根据过滤出路由表。如我会配置个asyncRoutes数组,需要认证的在其路由的meta中添加个roles字段... 查看详情

vue项目中使用路由导航守卫处理页面的访问权限(代码片段)

参考Vue-Router官方文档Vue-Router导航守卫效果展示1、给需要登录状态才能访问的页面路由对象的meta中添加配置属性//小智同学name:'user-chat',path:'/user/chat',component:()=>import('@/views/user-chat'),meta:requiresA 查看详情

vue-router路由所有相关方法讲解(全),实战教学含登录拦截,万字长文,建议收藏(代码片段)

目录router的基本使用main.jsApp.vuerouter文件夹下的index.js(抽离router)动态传参+编程式导航App.vueuser.vue组件 嵌套路由 路由传参,懒加载router的index.jsInfo组件User组件App.vue 守卫钩子(全局+独享+组件内的守卫)登录页... 查看详情

vue-router方法总结

参考技术A全局守卫:beforeEach(登录拦截)、afterEach路由独享守卫:beforeEnter(部分路由的登录拦截)组件内守卫:beforeRouteEnter(权限管理)、beforeRouteUpdate、beforeRouteLeave路由全局解析守卫:beforeResolve(这里根据单页面name的指... 查看详情

vue路由守卫

...进入的路由,离开之前的路由,下一个要进入的路由。在项目中我们一般使用路由来实现页面的鉴权,比如,当用户登陆之后,我们可以把后台返回的token或者用户的一些信息存入本地存储或vuex中,当用户跳转页面时,我们会在... 查看详情

vue3全局路由守卫(登录)

...放行//全局路由守卫:根据token判断,如果没有则返回登录页面,如果有则放行router.beforeEach((to,from,next)=> if(!localStorage.getItem('token&# 查看详情

vue实战(7):完整开发登录页面(一)

...技术Avue实战(1):准备与资料整理vue实战(2):初始化项目、搭建底部导航路由vue实战(3):底部导航显示、搭建各模块静态页面、添加登录页页面与路由vue实战(4):postman测试数据、封装ajax、使用vuex管理状态vue实战(5)... 查看详情

vue3全局路由守卫(登录)

...放行//全局路由守卫:根据token判断,如果没有则返回登录页面,如果有则放行router.beforeEach((to,from,next)=> if(!localStorage.getItem('token'))//如果没有 if(to.name=="login")//判断是否要去登陆界面如果是则放行 ... 查看详情

vue导航守卫,验证是否登录

路由跳转前,可以用导航守卫判断是否登录,如果登录了就正常跳转,没有登录就把路由指向登录页面。router.beforeEach((to, from, next) =>   const nextRoute = [ ‘api‘, ‘my/index, ‘course‘];&... 查看详情

vue项目常见之五:路由拦截器(permission),导航守卫(代码片段)

//处理路由拦截器导航守卫importrouterfrom‘../router‘importprogresssfrom‘nprogress‘import‘nprogress/nprogress.css‘//全局前置守卫当路由发生变化时这个方法里的回调函数就会执行router.beforeEach(function(to,from,next)progresss.start()//开启进度条//权... 查看详情

[vue项目实战]登录功能实现(代码片段)

登录功能实现写在前面登录概述登录业务流程登录业务的相关技术点登录---token原理分析登录功能实现登录页面的布局在components文件下创建一个vue文件配置路由(并添加路由重定向)页面编写完成登录框居中添加一个登录图标登录... 查看详情

vue中的导航守卫(路由守卫)(代码片段)

当做Vue-cli项目的时候感觉在路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。对此,vue-router提供的beforeEach可以方便地实现全局导航守卫(navigation-guards)。组件内部的导航守卫函数使用相同,只是函数名称不同(b... 查看详情

vue保存用户登录态逻辑完美实现(附代码)(代码片段)

1//路由守卫2router.beforeEach((to,from,next)=>3//获取用户登录成功后储存在本地的token4lettoken=localStorage.getItem("token")5//如果token存在,即用户已经登录过6if(token)7if(to.meta.requireAuth)8next()9else10next(path:‘/home‘)1112else13if(to.path===‘/home‘)14n... 查看详情

vue实战篇|使用路由管理用户权限(动态路由)

...相应的提示或者直接跳转到报错页面。跟着我一起来学vue实战篇路由管理权限吧!getCurrentAuthority()函数用于获取当前用户权限,一般来源于后台数据check()函数用于权限的校验匹配isLogin()函数用于检验用户是否登录路由配置元信息m... 查看详情

vue2.0实现导航守卫(路由守卫)

路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。对此,vue-route提供的beforeRouteUpdate可以方便地实现导航守卫(navigation-guards)。导航守卫(navigation-guards)这个名字,听起来怪怪的,但既然官方文档是这样翻译的,... 查看详情

vue权限管理深度探究

...2、路由的全局前置守卫(beforeEach)会判断路由用户是否登录(未登录跳转至登录界面),以及登录用户是否有权限查看该页面(无权限跳转至tips页面)。3、home中导航树根据权限信息的不同,渲染不同的页面。---------------------h... 查看详情