您好,登錄后才能下訂單哦!
本篇內容介紹了“怎么使用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<TypeResponse> { return instance.get('', { params }); }; function post(data: object, params?: object): Promise<TypeResponse> { 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設置路由守衛
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 })
大概就是這么多了
無痛刷新的原理:當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<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 }
“怎么使用vue3+ts+axios+pinia實現無感刷新”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。