摘要:接上篇議題合理的架構(gòu)討論上傳送門。處理思路如下使用上面定義的方法獲取如果能獲取到則說明有有效的,則時候即可跳轉(zhuǎn)到目標(biāo)頁如果獲取到空字符串,則說明無效或不存在,跳轉(zhuǎn)至登錄頁面。
接上篇《【Geek議題】合理的VueSPA架構(gòu)討論(上)》傳送門。
自動化維護(hù)登錄狀態(tài)登錄狀態(tài)標(biāo)識符跟token類似,都是需要自動維護(hù)有效期,但也有些許不同,獲取過程只在用戶登錄或注冊的時候,不需要自動獲取。
本人比較推薦使用公共狀態(tài)管理vuex進(jìn)行自動化管理,并配合路由鉤子,減少代碼編寫時的顧慮。
示例中公共狀態(tài)管理中的user模塊里定義了userIdObj,其中包含了userId登錄狀態(tài)標(biāo)識符和過期時間。
維護(hù)userId是否過期主要是通過vuex中的getter來實(shí)現(xiàn)。
const getters = {
getUserId: (_state) => {
// 獲取公共狀態(tài)中的userIdObj
const userIdObj = {
..._state.userIdObj,
};
// 是否過期標(biāo)識
let isExpire = false;
// 判斷是否過期
if (userIdObj && userIdObj.userId) {
isExpire = new Date().getTime() - userIdObj.expireTime > -10000;
}
// 如果過期則返回空字符串(不一定)
if (!userIdObj || !userIdObj.userId || isExpire) {
return "";
}
// 沒過期則返回userId
return userIdObj.userId;
},
};
路由鉤子中處理userId
回顧上篇中全局的路由鉤子router.beforeEach,當(dāng)目標(biāo)路由元信息requiresAuth為true則表示,這個路由必須有登錄狀態(tài)才能訪問,這時候就會進(jìn)行登錄狀態(tài)檢查。處理思路如下:
使用上面定義的getter方法獲取userId;
如果能獲取到則說明有有效的userId,則時候即可跳轉(zhuǎn)到目標(biāo)頁;
如果獲取到空字符串,則說明userId無效或userId不存在,跳轉(zhuǎn)至登錄頁面。
【PS】示例這里的處理還不完美,最好跳轉(zhuǎn)登錄前保存好目標(biāo)路由,登錄成功就直接跳轉(zhuǎn)去該路由。
router.beforeEach((to, from, next) => {
// ...
// 檢查登錄狀態(tài)
if (to.meta.requiresAuth) {
console.log("目標(biāo)路由需要登錄狀態(tài)");
if (!store.getters.getUserId) {
console.log("內(nèi)存無登錄信息,嘗試在本地存儲中找");
const localUserIdObj = JSON.parse(localStorage.getItem("userIdObj"));
if (localUserIdObj) {
// 如果本地存儲中有userIdObj,則提交到公共狀態(tài)
store.commit("setUserIdObj", localUserIdObj);
}
}
// 再次檢查公共狀態(tài)里有沒有userId
if (!store.getters.getUserId) {
console.log("依舊無登錄信息");
router.push({
name: "userLogin",
});
}
}
next();
});
”頁面”中獲取登錄狀態(tài)
在“頁面”中獲取userId也很簡單,使用計算屬性是最好的,返回的userId具有響應(yīng)性,這做的好處也是為了實(shí)時將登錄狀態(tài)反應(yīng)到頁面上,才不會出現(xiàn)顯示已登錄,但用戶刷新一下才能知道登錄狀態(tài)已過期的尷尬情況。
【PS】一些需要用戶登錄狀態(tài)的api函數(shù),也是通過這樣的方法獲取并使用。當(dāng)然,建議在非首屏加載使用的api函數(shù)(比如提交表單),需要在調(diào)用前,檢查一下userId還存不存在,以免出錯。
computed: {
// 獲取登錄狀態(tài)
userId() {
return this.$store.getters.getUserId;
},
},
使用公共狀態(tài)管理維護(hù)連接
有時會有需要取消請求的需求,比如上傳文件耗時過長,用戶不想等,這時候就必須有取消的功能。
上篇提到的axios已經(jīng)提供了一個基于CancelToken的取消機(jī)制,這里我們要配合vuex實(shí)現(xiàn)對全局連接的實(shí)時監(jiān)控。
【PS】示例的接口名稱都是在寫api函數(shù)的時候定義好的,想要更加靈活,可以每次請求都多帶帶指定名字。公共狀態(tài)管理配置
示例中給公共狀態(tài)下的com模塊添加了cancelToken數(shù)組,用來保存發(fā)起的連接的名稱和source(取消標(biāo)記),并提供了如下三個mutations方法
// 增加cancelToken
addCancelToken(_state, cancelToken) {
_state.cancelToken.push(cancelToken);
const arr = _state.cancelToken;
_state.cancelToken = arr;
},
// 刪除指定名字的cancelToken
deleteCancelToken(_state, name) {
_state.cancelToken.some((i, index) => {
if (i.name === name) {
_state.cancelToken.splice(index, 1);
return true;
}
return false;
});
},
// 清空cancelToken
clearCancelToken(_state) {
_state.cancelToken.forEach((i) => {
if (i.source && typeof i.source.cancel === "function") {
i.source.cancel(`cancel${name}`);
}
});
_state.cancelToken = [];
},
請求攔截器配置
基本思路:
在“請求發(fā)起前攔截器”中獲取到source(取消標(biāo)記),寫入請求配置,并提交名稱和source到公共狀態(tài)管理;
這時候通過查詢公共狀態(tài)中是否有這個名字的連接就可以獲取到source進(jìn)行取消;
在“響應(yīng)攔截器”中我們將已經(jīng)成功的請求在公共狀態(tài)管理中移除。
// 請求發(fā)起前攔截器
myAxios.interceptors.request.use((_config) => {
const config = _config;
const source = axios.CancelToken.source();
// 獲取cancelToken
config.cancelToken = source.token;
// 取消請求標(biāo)記保存
store.commit("addCancelToken", {
name: config.name,
source,
});
return config;
}, () => {
// 異常處理
console.error("請求發(fā)起前攔截器異常");
});
// 響應(yīng)攔截器
myAxios.interceptors.response.use((response) => {
// 刪除取消標(biāo)記
store.commit("deleteCancelToken", response.config.name);
console.log(response);
return response;
}, (error) => {
console.error(error);
// 清理取消標(biāo)記
store.commit("clearCancelToken");
return Promise.reject(error);
});
代碼中使用
使用計算屬性獲取cancelToken數(shù)組,這里是響應(yīng)式的,所有我們其實(shí)可以知道現(xiàn)在有多少個請求還未完成了。
【PS】實(shí)時對全局請求的監(jiān)控已經(jīng)實(shí)現(xiàn),其實(shí)可以做的擴(kuò)展就很多了,比如可以全局化loading的顯示,只要數(shù)組內(nèi)一直不為空持續(xù)一段時間就可以判斷需要顯示loading,如果為空則關(guān)閉loading。
computed: {
// 獲取連接列表
cancelToken() {
return this.$store.state.com.cancelToken;
},
},
遍歷這個數(shù)組,查找到對應(yīng)名字的連接就可以取消了。
this.cancelToken.forEach((i) => {
console.log(i);
if (i.name === "上傳文件" && typeof i.source.cancel === "function") {
console.log("取消上傳");
i.source.cancel(`cancel${name}`);
}
});
其他細(xì)節(jié)技巧
掛載常用工具到vue原型上減少引用
在初始化Vue的根組件前,給Vue的原型鏈上添加常用的工具,可以方便在vue文件中使用。這樣做會影響所有Vue示例推薦只在單頁面應(yīng)用中使用。
比如下面以我們的api集為例,這樣在vue文件中this.$api就可以使用我們的api集,不需要重復(fù)引用。
// 將api模塊掛載進(jìn)vue方便在this調(diào)用 Vue.prototype.$api = api;批量導(dǎo)入過濾器
在util文件夾下可以新建一個專門用來存過濾器的filter.js,然后批量導(dǎo)入的全局過濾器中。
import * as filters from "./util/filter"; Object.keys(filters).forEach(k => Vue.filter(k, filters[k]));
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/93858.html
摘要:接上篇議題合理的架構(gòu)討論上傳送門。處理思路如下使用上面定義的方法獲取如果能獲取到則說明有有效的,則時候即可跳轉(zhuǎn)到目標(biāo)頁如果獲取到空字符串,則說明無效或不存在,跳轉(zhuǎn)至登錄頁面。 接上篇《【Geek議題】合理的VueSPA架構(gòu)討論(上)》傳送門。 自動化維護(hù)登錄狀態(tài) 登錄狀態(tài)標(biāo)識符跟token類似,都是需要自動維護(hù)有效期,但也有些許不同,獲取過程只在用戶登錄或注冊的時候,不需要自動獲取。 ...
摘要:下面也是以模塊的模塊集為例,可以發(fā)現(xiàn)和路由有一些不同就是這里為了防止模塊跟全局耦合,運(yùn)用函數(shù)式編程思想類似于依賴注入,將全局的實(shí)例作為函數(shù)參數(shù)傳入,再返回出一個包含的對象,這個導(dǎo)出的對象將會被以模塊名命名,合并到全局的集中。 前言 web前端發(fā)展到現(xiàn)代,已經(jīng)不再是嚴(yán)格意義上的后端MVC的V層,它越來越向類似客戶端開發(fā)的方向發(fā)展,已獨(dú)立擁有了自己的MVVM設(shè)計模型。前后端的分離也使前端人...
摘要:下面也是以模塊的模塊集為例,可以發(fā)現(xiàn)和路由有一些不同就是這里為了防止模塊跟全局耦合,運(yùn)用函數(shù)式編程思想類似于依賴注入,將全局的實(shí)例作為函數(shù)參數(shù)傳入,再返回出一個包含的對象,這個導(dǎo)出的對象將會被以模塊名命名,合并到全局的集中。 前言 web前端發(fā)展到現(xiàn)代,已經(jīng)不再是嚴(yán)格意義上的后端MVC的V層,它越來越向類似客戶端開發(fā)的方向發(fā)展,已獨(dú)立擁有了自己的MVVM設(shè)計模型。前后端的分離也使前端人...
摘要:同源策略年,同源政策由公司引入瀏覽器。標(biāo)簽不受同源策略限制,但只能發(fā)起請求。這一行為使得不同域的特定文檔可以讀取該屬性值,因此可以繞過同源策略并使跨域消息通信成為可能。 前言 現(xiàn)在cross-origin resource sharing(跨域資源共享,下簡稱CORS)已經(jīng)十分普及,算上IE8的不標(biāo)準(zhǔn)兼容(XDomainRequest),各大瀏覽器基本都已支持,當(dāng)年為了前后端分離、if...
摘要:同源策略年,同源政策由公司引入瀏覽器。標(biāo)簽不受同源策略限制,但只能發(fā)起請求。這一行為使得不同域的特定文檔可以讀取該屬性值,因此可以繞過同源策略并使跨域消息通信成為可能。 前言 現(xiàn)在cross-origin resource sharing(跨域資源共享,下簡稱CORS)已經(jīng)十分普及,算上IE8的不標(biāo)準(zhǔn)兼容(XDomainRequest),各大瀏覽器基本都已支持,當(dāng)年為了前后端分離、if...
閱讀 3305·2021-09-03 10:33
閱讀 1498·2019-08-30 15:53
閱讀 2831·2019-08-30 15:45
閱讀 3579·2019-08-30 14:11
閱讀 760·2019-08-30 13:55
閱讀 2889·2019-08-29 15:24
閱讀 2120·2019-08-26 18:26
閱讀 3766·2019-08-26 13:41