search
HomeWeb Front-endVue.jsHow to use vue3+ts+axios+pinia to achieve senseless refresh

vue3 ts axios pinia achieves senseless refresh

1. First download aiXos and pinia in the project

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

2. Encapsulate axios request-----

Download 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<TypeResponse> {
    return instance.get(&#39;&#39;, { params });
};
function post(data: object, params?: object): Promise<TypeResponse> {
    return instance.post(&#39;&#39;, qs.stringify(data), { params });
};
 
 
//暴露实列
export {
    post, get,
}

3.qs.stringify(data) is to convert the requested data into a form format. If you don’t need it, just remove it directly;

4. Log in again and jump Routing needs to be set, if not needed you can remove

5. State management--data

Download persistence tool

npm install pinia-plugin-persistedstate --s

Configure persistence in main.js

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

6. Login page--Storage form data, that is, user Name and password

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

7.main.js Set routing guard

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

That’s about it

vue3 painless refresh (senseless refresh)

The principle of painless refresh: when the token expires, the response interceptor re-makes the login request through judgment

Implementation process

Define a loginInfo object in the state management state to store the user's account and password

//在状态管理文件中
import { defineStore } from &#39;pinia&#39;
import Cookies from "js.cookie"
import {post} from &#39;@/http&#39;
 
import router from &#39;@/router&#39;;
import { ElMessage } from &#39;element-plus&#39;;
export const useUserStore = defineStore({
  id: "userStore",
  persist: {
    paths:[&#39;user&#39;]
  },//持久化
  state: () => ({
    loginInfo:{
      username:&#39;&#39;, 
      password:&#39;&#39;
    }
  }),
  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(&#39;/login&#39;)
          ElMessage.success(errmsg);
        }else{
          ElMessage.error(errmsg);
        }
      }).catch(res=>{
      console.log(res,"退出登入失败");
      })
    }
  }
})

In the login page, after the login request is successful, the user's account and password are stored in the status management

//在登入页面文件中
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. In http, first define an array variable, which stores Operations that require painless refresh include: delete, add, edit

4. In the response interceptor, determine whether 10006 is equal to errno. If equal, the token has expired, otherwise it has not expired

5. The token expires. Get the interface request data and search it in the defined array to determine whether the request type requires painless refresh.

6.index===-1 means it is not found in the array, so there is no need to refresh it. Painful refresh, jump directly to the login page to log in

7.index! ==-1 means a painless refresh is required, deconstructing the user account and password stored in the status management, making a login interface request to re-obtain the token, and then making a login request without entering the login page. The effect of painless refresh

//在封装的http文件中
import axios, { type AxiosResponse } from &#39;axios&#39;;
import qs from &#39;qs&#39;
import Cookies from "js.cookie"
import router from &#39;@/router&#39;;
import { ElMessage } from &#39;element-plus&#39;;
import { useUserStore } from &#39;@/stores/admin&#39;;
 
declare interface TypeResponse extends AxiosResponse {
    url(url: any): unknown;
    [x: string]: any;
    /**
     * 错误号,200表示成功,10006令牌过期
     */
    errno: number,
    /**
     * 失败返回的消息
     */
    error: string,
    /**
     * 成功后返回的消息
    */
    errmsg: string
 
}
let baseURL = &#39;&#39;
 
if (process.env.NODE_ENV === "development") {
    baseURL = &#39;/m.api&#39;
} 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[&#39;AdminToken&#39;] = Cookies.get("token") + &#39;&#39;
    }
    return config
}, function (error) {
    console.error(&#39;请求错误&#39;, 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,&#39;errno&#39;);
    
    if (10006 == errno) {
        // 获取接口请求数据
        const configData = response.config.data || &#39;&#39;
        // 判断请求类型是否需要无痛刷新,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: &#39;admin&#39;, _mt: &#39;login&#39;, username, password };
            const { errno, errmsg, data } = await post(loginData)//这里是通过async 将异步序列化改为同步
            if (200 == errno) {
 
                Cookies.set(&#39;token&#39;, 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(&#39;响应错误&#39;, error)
    return Promise.reject(error)
}
)
function get(params?: object): Promise<TypeResponse> {
    return instance.get("", { params })
}
function post(data: object, params?: object): Promise<TypeResponse> {
    return instance.post("", qs.stringify(data), { params })
}
 
/**
 * 富文本框图片上传请求
 */
export function upload(data: object): Promise<TypeResponse> {
    return instance.post("http://192.168.1.188:8080/upload/admin", data);
}
 
export { get, post }

The above is the detailed content of How to use vue3+ts+axios+pinia to achieve senseless refresh. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:亿速云. If there is any infringement, please contact admin@php.cn delete
Netflix's Frontend: Examples and Applications of React (or Vue)Netflix's Frontend: Examples and Applications of React (or Vue)Apr 16, 2025 am 12:08 AM

Netflix uses React as its front-end framework. 1) React's componentized development model and strong ecosystem are the main reasons why Netflix chose it. 2) Through componentization, Netflix splits complex interfaces into manageable chunks such as video players, recommendation lists and user comments. 3) React's virtual DOM and component life cycle optimizes rendering efficiency and user interaction management.

The Frontend Landscape: How Netflix Approached its ChoicesThe Frontend Landscape: How Netflix Approached its ChoicesApr 15, 2025 am 12:13 AM

Netflix's choice in front-end technology mainly focuses on three aspects: performance optimization, scalability and user experience. 1. Performance optimization: Netflix chose React as the main framework and developed tools such as SpeedCurve and Boomerang to monitor and optimize the user experience. 2. Scalability: They adopt a micro front-end architecture, splitting applications into independent modules, improving development efficiency and system scalability. 3. User experience: Netflix uses the Material-UI component library to continuously optimize the interface through A/B testing and user feedback to ensure consistency and aesthetics.

React vs. Vue: Which Framework Does Netflix Use?React vs. Vue: Which Framework Does Netflix Use?Apr 14, 2025 am 12:19 AM

Netflixusesacustomframeworkcalled"Gibbon"builtonReact,notReactorVuedirectly.1)TeamExperience:Choosebasedonfamiliarity.2)ProjectComplexity:Vueforsimplerprojects,Reactforcomplexones.3)CustomizationNeeds:Reactoffersmoreflexibility.4)Ecosystema

The Choice of Frameworks: What Drives Netflix's Decisions?The Choice of Frameworks: What Drives Netflix's Decisions?Apr 13, 2025 am 12:05 AM

Netflix mainly considers performance, scalability, development efficiency, ecosystem, technical debt and maintenance costs in framework selection. 1. Performance and scalability: Java and SpringBoot are selected to efficiently process massive data and high concurrent requests. 2. Development efficiency and ecosystem: Use React to improve front-end development efficiency and utilize its rich ecosystem. 3. Technical debt and maintenance costs: Choose Node.js to build microservices to reduce maintenance costs and technical debt.

React, Vue, and the Future of Netflix's FrontendReact, Vue, and the Future of Netflix's FrontendApr 12, 2025 am 12:12 AM

Netflix mainly uses React as the front-end framework, supplemented by Vue for specific functions. 1) React's componentization and virtual DOM improve the performance and development efficiency of Netflix applications. 2) Vue is used in Netflix's internal tools and small projects, and its flexibility and ease of use are key.

Vue.js in the Frontend: Real-World Applications and ExamplesVue.js in the Frontend: Real-World Applications and ExamplesApr 11, 2025 am 12:12 AM

Vue.js is a progressive JavaScript framework suitable for building complex user interfaces. 1) Its core concepts include responsive data, componentization and virtual DOM. 2) In practical applications, it can be demonstrated by building Todo applications and integrating VueRouter. 3) When debugging, it is recommended to use VueDevtools and console.log. 4) Performance optimization can be achieved through v-if/v-show, list rendering optimization, asynchronous loading of components, etc.

Vue.js and React: Understanding the Key DifferencesVue.js and React: Understanding the Key DifferencesApr 10, 2025 am 09:26 AM

Vue.js is suitable for small to medium-sized projects, while React is more suitable for large and complex applications. 1. Vue.js' responsive system automatically updates the DOM through dependency tracking, making it easy to manage data changes. 2.React adopts a one-way data flow, and data flows from the parent component to the child component, providing a clear data flow and an easy-to-debug structure.

Vue.js vs. React: Project-Specific ConsiderationsVue.js vs. React: Project-Specific ConsiderationsApr 09, 2025 am 12:01 AM

Vue.js is suitable for small and medium-sized projects and fast iterations, while React is suitable for large and complex applications. 1) Vue.js is easy to use and is suitable for situations where the team is insufficient or the project scale is small. 2) React has a richer ecosystem and is suitable for projects with high performance and complex functional needs.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
4 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool