0

0

怎么使用vue3+ts+axios+pinia实现无感刷新

PHPz

PHPz

发布时间:2023-05-25 15:37:06

|

1934人浏览过

|

来源于亿速云

转载

vue3+ts+axios+pinia实现无感刷新

1.先在项目中下载aixos和pinia

npm i pinia --save
npm install axios --save

2.封装axios请求-----

下载js-cookie

npm i JS-cookie -s
//引入aixos
import type { AxiosRequestConfig, AxiosResponse } from "axios";
import axios from 'axios';
import { ElMessage } from 'element-plus';
import { useUserInfoStore } from '@/stores/modules/UserInfo'
import router from '@/router';
import qs from 'qs';
import Cookie from "js-cookie";
let baseURL = "";
// console.log(process.env.NODE_ENV);//判断环境
if (process.env.NODE_ENV === 'development') {
    baseURL = '/m.api'//后台请求接口地址
} else {
    baseURL = 'http://xxxx.cn:8080';//这里是项目上线后的地址
   
}
declare interface TypeResponse extends AxiosResponse {
    /**
     * 错误号,200表示成功,10006令牌过期
     */
    errno: number,
    /**
     * 返回的信息
     */
    errmsg: string
}
 
//创建axios实例
 
const instance = axios.create({
    baseURL,  // 接口地址
    timeout: 3000,
    headers: {
        "Content-Type": 'application/x-www-form-urlencoded'
    }
 
});
 
 
//添加拦截器
instance.interceptors.request.use((config) => {
    // 在发送请求之前做些什么--给请求头添加令牌token
    (config as any).headers['AdminToken'] = Cookie.get('token')//从cookie中拿token值,
//这里是使用了js-cookie插件。
    // console.log(config, "请求拦截器")
    return config
}, reeor => {
    // 对请求错误做些什么
    return Promise.reject(reeor);
});
// 需要无痛刷新的操作页面
const METHOD_TYPE = ["_mt=edit", "_mt=create", "_mt=delete"]
// //响应拦截器
instance.interceptors.response.use(async (response: AxiosResponse) => {
    // 对响应数据做点什么
    let data = response.data;
    let { errno, errmsg } = data;
    console.log(response, "响应拦截器");
    let path = router.currentRoute.value.fullPath;//当前路由路径
    if (10006 === errno) {
        const configData = response.config.data || ''
        // 判断请求类型是否需要无痛刷新,index !== -1则需要无痛刷新
        let index = METHOD_TYPE.findIndex(item => configData.includes(item))
        if (-1 === index) {//需要重新登入获取令牌
            router.replace({ path: "/login", query: { back: path } })//登入后需要跳回的地址
            return
        } else {//需要无痛刷新令牌
            const store = useUserInfoStore();
            const { username, password } = store.LoginInfo//在状态管理里面定义一个loginInfo
            // 1.重新获取令牌
            let loginData = { _gp: 'admin', _mt: 'login', username, password };
            const { errno, errmsg, data } = await post(loginData)//这里是通过async 将异步序列化改为同步
            if (200 == errno) {
                Cookie.set('token', data)//保存令牌
            } else {
                router.replace({ path: "/login", query: { back: path } })//登入后需要跳回的地址
                return Promise.reject({ errno, errmsg, data })
            }
            return instance.request(response.config)
        }
    // ElMessage.error(errmsg);//错误信息
    }
    return data;
}, reeor => {
    console.log(reeor);
 
    return Promise.reject(reeor);
})
 
function get(params?: object): Promise {
    return instance.get('', { params });
};
function post(data: object, params?: object): Promise {
    return instance.post('', qs.stringify(data), { params });
};
 
 
//暴露实列
export {
    post, get,
}

3.qs.stringify(data)是将请求的数据转成表单格式,如果不需要直接去掉就可以了;

4.重新登录后跳转路由需要设置,不需要可以去掉

立即学习前端免费学习笔记(深入)”;

5。状态管理--数据

下载持久化工具

npm install pinia-plugin-persistedstate --s

在main.js中配置持久化

//引入数据持久化插件
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate);
app.use(pinia)
import { defineStore } from 'pinia'
export const useUserInfoStore = defineStore('UserInfo', {
    state:() => ({
       
        LoginInfo:{
            username:'',
            password:''
        }
      }),
     
      persist:true;//状态存储持久化
})

6.登录页面--存储表单数据,也就是用户名和密码

npm i lodash --s
import Cookies from 'js-cookie';//引入cookie
import * as _ from 'lodash';//防抖节流插件
import {post} from '@/util';
import {useUserInfoStore} from '@/stores/modules/UserInfo' ;//用户信息
import { useRouter,useRoute } from 'vue-router' ;//引入路由
//这里是表单输入的数据
const ruleForm = reactive({
    password: '123456',
    username: 'admin'
});
//请求接口数据
let data = {
    _gp: "admin",
    _mt: 'login',
    ...ruleForm
};
 
let LoginInfo = useUserInfoStore().LoginInfo;//状态管理定义的数据
async function init() {
    await post(data).then((res:any) => {
        let { data: token, errno, errmsg } = res
        if (200 === errno) {
            let time = new Date() //设置过期时间
            time.setTime(time.getTime() + 1000 * 60 * 30)
            Cookies.set('token', token, { expires: time });
            Object.assign(LoginInfo,ruleForm)
            if (route.query.back) { //如果存在参数
             let paths = route.query.back+''//拼接字符串
             console.log(paths);
             if (paths=='/') {
//因为我的home是'/',所有需要判断
                router.replace('/Surface')//跳转至主页
                return
             }else{
                router.replace(paths)//则跳转至进入登录页前的路由
             }
             
           } else {
            router.replace('/Surface')//否则跳转至首页
           }
            
        } else {
            ElMessage.error(errmsg)
        }
    }).catch((err:any) => {
        ElMessage.error('登录异常!')
    })
    let info = {//用户信息请求信息接口数据
        _gp: "admin",
        _mt: 'info',
    }
//下面这个函数是请求用户信息的,不需要可以不写
    await post(info).then((res:any) => {
        let {data} = res
        console.log(data);
        infos(data)
 
    }).catch((err:any)=>{
        ElMessage.error('登录异常!')
    })
}
//防抖节流
const fangdou = _.debounce(init, 1500, {
    leading: true,  // 延长开始后调用
    trailing: false  // 延长结束前调用
})
//移除组件时,取消防抖
onUnmounted(() => {
    fangdou.cancel()
})

7.main.js设置路由守卫

Simplified
Simplified

AI写作、平面设计、编辑视频和发布内容。专为团队打造。

下载
import Cookie from 'js-cookie'
import router from './router'//引入路由
 
//路由守卫
router.beforeEach(async (to, from ) => {
    let tokent:string|undefined = Cookie.get('token')
    if (!tokent && to.path == '/login') {
        return  true
    }
    // 没有登录,强制跳转登录页
    if (!tokent && to.path !== '/login') {
        router.replace({path:'/login',query:{back:to.path}});
    }
    // 防止重复登录
    if (tokent && to.path === '/login') {
        return {
            path: from.path ? from.path : '/Surface'
        }
    }
    return true
})

大概就是这么多了

vue3无痛刷新(无感刷新)

无痛刷新的原理:当token过期后,在响应拦截器通过判断重新进行登入请求

实现过程

在状态管理state中定义一个loginInfo对象用于存储用户的账号和密码

//在状态管理文件中
import { defineStore } from 'pinia'
import Cookies from "js.cookie"
import {post} from '@/http'
 
import router from '@/router';
import { ElMessage } from 'element-plus';
export const useUserStore = defineStore({
  id: "userStore",
  persist: {
    paths:['user']
  },//持久化
  state: () => ({
    loginInfo:{
      username:'', 
      password:''
    }
  }),
  getters: {},
  actions: {
    setUser(user:UserInfo) {
      this.user = user;
    },
    loginOut(){
      const data ={
        _gp:"admin",
        _mt:"logout"
      }
      post({},data).then((res:any)=>{
        let {errmsg,errno} = res
        if(200==errno){
          localStorage.removeItem("userStore")
          Cookies.remove("token")
          router.replace('/login')
          ElMessage.success(errmsg);
        }else{
          ElMessage.error(errmsg);
        }
      }).catch(res=>{
      console.log(res,"退出登入失败");
      })
    }
  }
})

登入页面中,在登入请求成功后将用户的账号和密码存储在状态管理

//在登入页面文件中
const data = { ...ruleForm, _gp: "admin", _mt: "login" }//转换成字符串
post({}, data).then(res => {
    let { data: token, errmsg, errno } = res as any;//获取登录状态
    if (200 == errno) {//登录成功的判断
        ElMessage.success("登录成功!")//消息提示登录成功
        let now = new Date();//获取当前时间
        now.setTime(now.getTime() + 1000 * 60 * 30);//转成时间类型
        Cookies.set("token", res.data, { expires: now })//获取token存到cookie
        Object.assign(store.loginInfo, ruleForm)//将账号密码存储到状态管理
        return Promise.resolve(token)
    } else {
        ElMessage.error(errmsg);//登入失败
        return Promise.reject(errmsg)
    }
})

3.在http中,先定义一个数组变量,该数组存放需要无痛刷新的操作如:删除、添加、编辑

4.在响应拦截器中,判断10006是否等于errno,如果相等说明令牌过期了,否则没过期

5.令牌过期,获取接口请求数据在定义的数组中查找判断请求类型是否需要无痛刷新

6.index===-1则表示在数组中没有找到也就不需要无痛刷新,直接跳到登入页面进行登入

7.index!==-1则表示需要无痛刷新,将状态管理中存储的用户账号和密码解构出来,进行登入接口请求从而达到重新获取令牌,进而达到不需要进入登入页面就可以进行登入请求也就达到无痛刷新的效果

//在封装的http文件中
import axios, { type AxiosResponse } from 'axios';
import qs from 'qs'
import Cookies from "js.cookie"
import router from '@/router';
import { ElMessage } from 'element-plus';
import { useUserStore } from '@/stores/admin';
 
declare interface TypeResponse extends AxiosResponse {
    url(url: any): unknown;
    [x: string]: any;
    /**
     * 错误号,200表示成功,10006令牌过期
     */
    errno: number,
    /**
     * 失败返回的消息
     */
    error: string,
    /**
     * 成功后返回的消息
    */
    errmsg: string
 
}
let baseURL = ''
 
if (process.env.NODE_ENV === "development") {
    baseURL = '/m.api'
} else {
    baseURL = "http://zxwyit.cn:8080/m.api"//上线后的路径
}
 
const instance = axios.create({//创建实例
    baseURL,
    headers: { "content-type": "application/x-www-form-urlencoded" }
})
 
// 请求拦截器
instance.interceptors.request.use(function (config) {
    if (config.headers) {
        config.headers['AdminToken'] = Cookies.get("token") + ''
    }
    return config
}, function (error) {
    console.error('请求错误', error)
    return Promise.reject(error)
}
)
// 无痛刷新的原理:当token过期后,在响应拦截器通过判断重新进行登入请求
// 实现过程:
// 1.在状态管理state中定义一个loginInfo对象用于存储用户的账号和密码
// 2.登入页面中,在登入请求成功后将用户的账号和密码存储在状态管理
// 3.在http中,先定义一个数组变量,该数组存放需要无痛刷新的操作如:删除、添加、编辑
// 4.在响应拦截器中,判断10006是否等于errno,如果相等说明令牌过期了,否则没过期
// 5.令牌过期,获取接口请求数据在定义的数组中查找判断请求类型是否需要无痛刷新
// 6.index===-1则表示在数组中没有找到也就不需要无痛刷新,直接跳到登入页面进行登入
// 7.index!==-1则表示需要无痛刷新,将状态管理中存储的用户账号和密码解构出来,
// 进行登入接口请求从而达到重新获取令牌,进而达到不需要进入登入页面就可以进行登入请求也就达到无痛刷新的效果
 
// 需要无痛刷新的操作页面
const METHOD_TYPE = ["_mt=edit", "_mt=create", "_mt=delete"]
// 响应拦截器
instance.interceptors.response.use(async function (response) {
    let data = response.data//强解
    let { errno, errmsg } = data//结构赋值
    let path = router.currentRoute.value.fullPath//获取路径
    console.log(errno,'errno');
    
    if (10006 == errno) {
        // 获取接口请求数据
        const configData = response.config.data || ''
        // 判断请求类型是否需要无痛刷新,index !== -1则需要无痛刷新
        let index = METHOD_TYPE.findIndex(item => configData.includes(item))
        if (-1 === index) {//需要重新登入获取令牌
            router.replace({ path: "/login", query: { back: path } })//登入后需要跳回的地址
            return
        } else {//需要无痛刷新令牌
            const store = useUserStore();
            const { username, password } = store.loginInfo//在状态管理里面定义一个loginInfo
            // 1.重新获取令牌
            let loginData = { _gp: 'admin', _mt: 'login', username, password };
            const { errno, errmsg, data } = await post(loginData)//这里是通过async 将异步序列化改为同步
            if (200 == errno) {
 
                Cookies.set('token', data)//保存令牌
            } else {
        console.log(55);
 
                router.replace({ path: "/login", query: { back: path } })//登入后需要跳回的地址
                return Promise.reject({ errno, errmsg,data})
            }
            return instance.request(response.config)
        }
    }
    return data
}, function (error) {
    console.error('响应错误', error)
    return Promise.reject(error)
}
)
function get(params?: object): Promise {
    return instance.get("", { params })
}
function post(data: object, params?: object): Promise {
    return instance.post("", qs.stringify(data), { params })
}
 
/**
 * 富文本框图片上传请求
 */
export function upload(data: object): Promise {
    return instance.post("http://192.168.1.188:8080/upload/admin", data);
}
 
export { get, post }

相关专题

更多
Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

3

2026.01.20

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

55

2026.01.19

java用途介绍
java用途介绍

本专题整合了java用途功能相关介绍,阅读专题下面的文章了解更多详细内容。

67

2026.01.19

java输出数组相关教程
java输出数组相关教程

本专题整合了java输出数组相关教程,阅读专题下面的文章了解更多详细内容。

36

2026.01.19

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

10

2026.01.19

xml格式相关教程
xml格式相关教程

本专题整合了xml格式相关教程汇总,阅读专题下面的文章了解更多详细内容。

11

2026.01.19

PHP WebSocket 实时通信开发
PHP WebSocket 实时通信开发

本专题系统讲解 PHP 在实时通信与长连接场景中的应用实践,涵盖 WebSocket 协议原理、服务端连接管理、消息推送机制、心跳检测、断线重连以及与前端的实时交互实现。通过聊天系统、实时通知等案例,帮助开发者掌握 使用 PHP 构建实时通信与推送服务的完整开发流程,适用于即时消息与高互动性应用场景。

15

2026.01.19

微信聊天记录删除恢复导出教程汇总
微信聊天记录删除恢复导出教程汇总

本专题整合了微信聊天记录相关教程大全,阅读专题下面的文章了解更多详细内容。

152

2026.01.18

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

139

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.4万人学习

Vue3.x 核心篇--十天技能课堂
Vue3.x 核心篇--十天技能课堂

共30课时 | 1.5万人学习

Vue3.x新特性篇--十天基础课堂
Vue3.x新特性篇--十天基础课堂

共20课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号