main.js引入permission.js
permission中使用router.beforeEach进行全局的路由拦截。
场景:
1、任何用户,都要获取用户地理位置。getUserLocation接口
2、免登录白名单不需要登录接口,非免登录白名单需要登录信息。getUserLogin接口获取用户信息
逻辑:
单页面应用,main.js只加载一次,路由跳转不再次进入。所以getUserLocation接口这里调用
1、main.js中
store.dispatch('getUserLocation').then(() => {
console.log('位置成功')
}, () => {
console.log('位置失败')
}).finally(() => { // 为了保证一定加载完接口用finally
app.use(router)
app.mount('#app');
})
获取用户信息,使用了.then方法。要有new Promise 进行返回才ok
getUserLogin接口调用,需要在router.beforeEach,看时机调用。
路由中设置meta.auth为true,这种页面需要用到vuex中的oldToken做请求接口头中的auth。所以必要的时候要调用getUserLogin接口。
逻辑:
const auth = to.meta?.auth
// 当该页面需要权限&&该页面的url上有token&&vuex中没有存储过
if (auth && to.query.token && !store.getters.userInfo.ecode) {
store.dispatch('init').then((res) => {
if(JSON.stringify(res)!=='{}'){
next({ // 再次进入该路由,由于vuex中存了userInfo,会打印aaaa
...to
})
}else{ // 当oldToken请求userLogin返回resultCode: -99时候,res为{}
next(false) // 中断当前路由,接口-99,axios中的相应拦截器,跳转了异常页面,异常页面属于免登录白名单
}
}).catch(() => {
next('/emptyPage') //请求userLogin接口过程中接口报错进入空白
})
} else {
console.log('aaaa')
next()
}
store.dispatch('init')发生了什么?
async init({ dispatch, commit }) {
// 从url中获取token=>放入存储,之后每次更新
let { token = '', ecode = '' } = Tools.getUrlQuery(window.location.href);
commit('SET_OLDTOKEN', token)
if (!token) {
return Promise.reject();
}
try {
const params = {
token,
ecode
}
return await dispatch('getUserLogin', params)
} catch (err) {
return Promise.reject()
}
},
async getUserLogin({ commit }, params) {
if (!params.token) {
return Promise.reject()
}
try {
const resData = await getUserLogin(params)
const userInfo = resData?.user || {};
commit('SET_USERINFO', userInfo)
return Promise.resolve(userInfo)
} catch (err) {
return Promise.reject()
}
},
需要注意的点:
1、vuex存储数据,页面刷新数据丢失。需要使用持久化缓存
npm install --save vuex-persistedstate
import createPersistedState from "vuex-persistedstate";
只需要在actions的同级下配置:
plugins: [
createPersistedState({
key: "vuexInfo", // 存储的key
storage: window.sessionStorage, // 使用的sessionStorage
})
]
// storage: window.localStorage, //选择 localStorage 进行存储
注意这里,使用了持久化插件后,不用你赋值,直接会赋值的
state() {
return { //storage中的值直接赋值,不用单独再赋值
userInfo: {},
token: '', // 子工程接口请求回来的token
oldToken: '', // url上自带的token
userLocation: {}
}
},
想要使用存储到cookie的配置如下:
具体网址:
https://blog.csdn.net/weixin_55042716/article/details/123107602
===============继续===================
那我使用持久化存储解决了什么问题呢?
1、我页面带token的,第一次请求完getUserLogin,刷新页面,vuex中还是有,不用再调接口
2、我从带token的页面,跳转到不带token的页面。每次热更新页面,加载页面,不怕vuex中数据丢失,造成的接口headers中auth为null造成的问题。
那给我带来了什么麻烦么?
我sessionStorage进行数据存储。我需要彻底关闭网页才能消掉缓存。
我在地址栏输入网址,走getUserLogin,存vuex,持久存。刷新还有。我更换账户token,该地址栏输入新的网址,url上的token肯定是新的。但是由于我持久化存储。不可能再次走dispatch('init'),拿取的数据就不对
===================我要怎么做====================
清除缓存。
问题1、如何清。怎么存的怎么清除。用commit()清除vuex中state的值,sessionStorage中的就会清掉。
问题2、在哪里清除。临界条件是什么?
肯定是全局清。
main.js?工程加载会清,从a页面push到b页面不会清
似乎满足了条件。
main.js是加载全局资源的,在这里处理缓存问题感觉不妥当。
export function clearStorage() {
store.commit("setUser", {});
store.commit("SET_OLDTOKEN", "");
store.commit("setOrganizations", []);
}
permission.js的路由拦截器外面?
只要加载页面就会进入路由拦截器。看来也能清掉。但是清掉后。从带token的网址跳转到不带token的网址,也把缓存清掉了,注意这里vuex中是有的。之前做的持久化缓存没意义了。
解决:加清除的判断
const auth = to.meta?.auth;
let { token = "" } = Tools.getUrlQuery(window.location.href);
let storeToken = store.getters.oldToken;
// url有token并且store不一致,清缓存
// 浏览器缓存原因,一个页签换token要敲2次enter,uuid待加
if (token && token !== storeToken) {
clearStorage();
}
==============经历=======================
beforeEach中调用next(),必须逻辑很清晰,多一个next(),少一个next()都报错或者警告
axios中统一拦截,接口返回-99,跳转到异常界面