How to use vue3+ts+axios+pinia to achieve senseless refresh
May 25, 2023 pm 03:37 PMvue3 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);//判斷環(huán)境 if (process.env.NODE_ENV === 'development') { baseURL = '/m.api'//后臺(tái)請(qǐng)求接口地址 } else { baseURL = 'http://xxxx.cn:8080';//這里是項(xiàng)目上線后的地址 } declare interface TypeResponse extends AxiosResponse { /** * 錯(cuò)誤號(hào),200表示成功,10006令牌過期 */ errno: number, /** * 返回的信息 */ errmsg: string } //創(chuàng)建axios實(shí)例 const instance = axios.create({ baseURL, // 接口地址 timeout: 3000, headers: { "Content-Type": 'application/x-www-form-urlencoded' } }); //添加攔截器 instance.interceptors.request.use((config) => { // 在發(fā)送請(qǐng)求之前做些什么--給請(qǐng)求頭添加令牌token (config as any).headers['AdminToken'] = Cookie.get('token')//從cookie中拿token值, //這里是使用了js-cookie插件。 // console.log(config, "請(qǐng)求攔截器") return config }, reeor => { // 對(duì)請(qǐng)求錯(cuò)誤做些什么 return Promise.reject(reeor); }); // 需要無痛刷新的操作頁面 const METHOD_TYPE = ["_mt=edit", "_mt=create", "_mt=delete"] // //響應(yīng)攔截器 instance.interceptors.response.use(async (response: AxiosResponse) => { // 對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么 let data = response.data; let { errno, errmsg } = data; console.log(response, "響應(yīng)攔截器"); let path = router.currentRoute.value.fullPath;//當(dāng)前路由路徑 if (10006 === errno) { const configData = response.config.data || '' // 判斷請(qǐng)求類型是否需要無痛刷新,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//在狀態(tài)管理里面定義一個(gè)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);//錯(cuò)誤信息 } return data; }, reeor => { console.log(reeor); return Promise.reject(reeor); }) 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 }); }; //暴露實(shí)列 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
//引入數(shù)據(jù)持久化插件 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;//狀態(tài)存儲(chǔ)持久化 })
6. Login page--Storage form data, that is, user Name and password
npm i lodash --s import Cookies from 'js-cookie';//引入cookie import * as _ from 'lodash';//防抖節(jié)流插件 import {post} from '@/util'; import {useUserInfoStore} from '@/stores/modules/UserInfo' ;//用戶信息 import { useRouter,useRoute } from 'vue-router' ;//引入路由 //這里是表單輸入的數(shù)據(jù) const ruleForm = reactive({ password: '123456', username: 'admin' }); //請(qǐng)求接口數(shù)據(jù) let data = { _gp: "admin", _mt: 'login', ...ruleForm }; let LoginInfo = useUserInfoStore().LoginInfo;//狀態(tài)管理定義的數(shù)據(jù) async function init() { await post(data).then((res:any) => { let { data: token, errno, errmsg } = res if (200 === errno) { let time = new Date() //設(shè)置過期時(shí)間 time.setTime(time.getTime() + 1000 * 60 * 30) Cookies.set('token', token, { expires: time }); Object.assign(LoginInfo,ruleForm) if (route.query.back) { //如果存在參數(shù) let paths = route.query.back+''//拼接字符串 console.log(paths); if (paths=='/') { //因?yàn)槲业膆ome是'/',所有需要判斷 router.replace('/Surface')//跳轉(zhuǎn)至主頁 return }else{ router.replace(paths)//則跳轉(zhuǎn)至進(jìn)入登錄頁前的路由 } } else { router.replace('/Surface')//否則跳轉(zhuǎn)至首頁 } } else { ElMessage.error(errmsg) } }).catch((err:any) => { ElMessage.error('登錄異常!') }) let info = {//用戶信息請(qǐng)求信息接口數(shù)據(jù) _gp: "admin", _mt: 'info', } //下面這個(gè)函數(shù)是請(qǐng)求用戶信息的,不需要可以不寫 await post(info).then((res:any) => { let {data} = res console.log(data); infos(data) }).catch((err:any)=>{ ElMessage.error('登錄異常!') }) } //防抖節(jié)流 const fangdou = _.debounce(init, 1500, { leading: true, // 延長(zhǎng)開始后調(diào)用 trailing: false // 延長(zhǎng)結(jié)束前調(diào)用 }) //移除組件時(shí),取消防抖 onUnmounted(() => { fangdou.cancel() })
7.main.js Set routing guard
import Cookie from 'js-cookie' import router from './router'//引入路由 //路由守衛(wèi) router.beforeEach(async (to, from ) => { let tokent:string|undefined = Cookie.get('token') if (!tokent && to.path == '/login') { return true } // 沒有登錄,強(qiáng)制跳轉(zhuǎn)登錄頁 if (!tokent && to.path !== '/login') { router.replace({path:'/login',query:{back:to.path}}); } // 防止重復(fù)登錄 if (tokent && to.path === '/login') { return { path: from.path ? from.path : '/Surface' } } 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
//在狀態(tài)管理文件中 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,"退出登入失敗"); }) } } })
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" }//轉(zhuǎn)換成字符串 post({}, data).then(res => { let { data: token, errmsg, errno } = res as any;//獲取登錄狀態(tài) if (200 == errno) {//登錄成功的判斷 ElMessage.success("登錄成功!")//消息提示登錄成功 let now = new Date();//獲取當(dāng)前時(shí)間 now.setTime(now.getTime() + 1000 * 60 * 30);//轉(zhuǎn)成時(shí)間類型 Cookies.set("token", res.data, { expires: now })//獲取token存到cookie Object.assign(store.loginInfo, ruleForm)//將賬號(hào)密碼存儲(chǔ)到狀態(tài)管理 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 '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; /** * 錯(cuò)誤號(hào),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({//創(chuàng)建實(shí)例 baseURL, headers: { "content-type": "application/x-www-form-urlencoded" } }) // 請(qǐng)求攔截器 instance.interceptors.request.use(function (config) { if (config.headers) { config.headers['AdminToken'] = Cookies.get("token") + '' } return config }, function (error) { console.error('請(qǐng)求錯(cuò)誤', error) return Promise.reject(error) } ) // 無痛刷新的原理:當(dāng)token過期后,在響應(yīng)攔截器通過判斷重新進(jìn)行登入請(qǐng)求 // 實(shí)現(xiàn)過程: // 1.在狀態(tài)管理state中定義一個(gè)loginInfo對(duì)象用于存儲(chǔ)用戶的賬號(hào)和密碼 // 2.登入頁面中,在登入請(qǐng)求成功后將用戶的賬號(hào)和密碼存儲(chǔ)在狀態(tài)管理 // 3.在http中,先定義一個(gè)數(shù)組變量,該數(shù)組存放需要無痛刷新的操作如:刪除、添加、編輯 // 4.在響應(yīng)攔截器中,判斷10006是否等于errno,如果相等說明令牌過期了,否則沒過期 // 5.令牌過期,獲取接口請(qǐng)求數(shù)據(jù)在定義的數(shù)組中查找判斷請(qǐng)求類型是否需要無痛刷新 // 6.index===-1則表示在數(shù)組中沒有找到也就不需要無痛刷新,直接跳到登入頁面進(jìn)行登入 // 7.index!==-1則表示需要無痛刷新,將狀態(tài)管理中存儲(chǔ)的用戶賬號(hào)和密碼解構(gòu)出來, // 進(jìn)行登入接口請(qǐng)求從而達(dá)到重新獲取令牌,進(jìn)而達(dá)到不需要進(jìn)入登入頁面就可以進(jìn)行登入請(qǐng)求也就達(dá)到無痛刷新的效果 // 需要無痛刷新的操作頁面 const METHOD_TYPE = ["_mt=edit", "_mt=create", "_mt=delete"] // 響應(yīng)攔截器 instance.interceptors.response.use(async function (response) { let data = response.data//強(qiáng)解 let { errno, errmsg } = data//結(jié)構(gòu)賦值 let path = router.currentRoute.value.fullPath//獲取路徑 console.log(errno,'errno'); if (10006 == errno) { // 獲取接口請(qǐng)求數(shù)據(jù) const configData = response.config.data || '' // 判斷請(qǐng)求類型是否需要無痛刷新,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//在狀態(tài)管理里面定義一個(gè)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('響應(yīng)錯(cuò)誤', 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 }) } /** * 富文本框圖片上傳請(qǐng)求 */ 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!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

It is very common to use axios in Vue applications. axios is a Promise-based HTTP client that can be used in browsers and Node.js. During the development process, the error message "Uncaught(inpromise)Error: Requestfailedwithstatuscode500" sometimes appears. For developers, this error message may be difficult to understand and solve. This article will explore this

Choice of data request in Vue: AxiosorFetch? In Vue development, handling data requests is a very common task. Choosing which tool to use for data requests is a question that needs to be considered. In Vue, the two most common tools are Axios and Fetch. This article will compare the pros and cons of both tools and give some sample code to help you make your choice. Axios is a Promise-based HTTP client that works in browsers and Node.

How to solve the problem of "Error: NetworkError" when using axios in Vue application? In the development of Vue applications, we often use axios to make API requests or obtain data, but sometimes we encounter "Error: NetworkError" in axios requests. What should we do in this case? First of all, you need to understand what "Error:NetworkError" means. It usually means that the network connection

Recently, during the development of Vue applications, I encountered a common problem: "TypeError: Failedtofetch" error message. This problem occurs when using axios to make HTTP requests and the backend server does not respond to the request correctly. This error message usually indicates that the request cannot reach the server, possibly due to network reasons or the server not responding. What should we do after this error message appears? Here are some workarounds: Check your network connection due to

The final effect is to install the VueCropper component yarnaddvue-cropper@next. The above installation value is for Vue3. If it is Vue2 or you want to use other methods to reference, please visit its official npm address: official tutorial. It is also very simple to reference and use it in a component. You only need to introduce the corresponding component and its style file. I do not reference it globally here, but only introduce import{userInfoByRequest}from'../js/api' in my component file. import{VueCropper}from'vue-cropper&

Efficiently utilize Vue and Axios to implement batch processing of front-end data. In front-end development, data processing is a common task. When we need to process a large amount of data, processing the data will become very cumbersome and inefficient if there is no effective method. Vue is an excellent front-end framework, and Axios is a popular network request library. They can work together to implement batch processing of front-end data. This article will introduce in detail how to efficiently use Vue and Axios for batch processing of data, and provide relevant code examples.

What should I do if "Error: timeoutofxxxmsexceeded" occurs when using axios in a Vue application? With the rapid development of the Internet, front-end technology is constantly updated and iterated. As an excellent front-end framework, Vue has been welcomed by everyone in recent years. In Vue applications, we often need to use axios to make network requests, but sometimes the error "Error: timeoutofxxxmsexceeded" occurs.

A complete guide to implementing file upload in Vue (axios, element-ui) In modern web applications, file upload has become a basic function. Whether uploading avatars, pictures, documents or videos, we need a reliable way to upload files from the user's computer to the server. This article will provide you with a detailed guide on how to use Vue, axios and element-ui to implement file upload. What is axiosaxios is a prom based
