摘要:下面也是以模塊的模塊集為例,可以發(fā)現(xiàn)和路由有一些不同就是這里為了防止模塊跟全局耦合,運(yùn)用函數(shù)式編程思想類似于依賴注入,將全局的實(shí)例作為函數(shù)參數(shù)傳入,再返回出一個(gè)包含的對(duì)象,這個(gè)導(dǎo)出的對(duì)象將會(huì)被以模塊名命名,合并到全局的集中。
前言
web前端發(fā)展到現(xiàn)代,已經(jīng)不再是嚴(yán)格意義上的后端MVC的V層,它越來(lái)越向類似客戶端開(kāi)發(fā)的方向發(fā)展,已獨(dú)立擁有了自己的MVVM設(shè)計(jì)模型。前后端的分離也使前端人員擁有更大的自由,可以獨(dú)立設(shè)計(jì)客戶端部分的架構(gòu)。
【科普】MVVM是Model-View-ViewModel的簡(jiǎn)寫(xiě)。它本質(zhì)上就是MVC 的改進(jìn)版。MVVM 就是將其中的View 的狀態(tài)和行為抽象化,讓我們將視圖 UI 和業(yè)務(wù)邏輯分開(kāi)。當(dāng)然這些事 ViewModel 已經(jīng)幫我們做了,它可以取出 Model 的數(shù)據(jù)同時(shí)幫忙處理 View 中由于需要展示內(nèi)容而涉及的業(yè)務(wù)邏輯。
Vue作為現(xiàn)在流行的MVVM框架,也是本人平常業(yè)務(wù)中用得最多的框架。如何才能更合理、優(yōu)雅的寫(xiě)VueSPA,是本人一直研究的課題,經(jīng)過(guò)一年左右的思考和實(shí)踐總結(jié)出本文。
本文屬于中高級(jí)實(shí)踐討論,不適合新手。
本人個(gè)人的觀點(diǎn),不代表是最佳實(shí)踐,歡迎大牛一起討論,批評(píng)指正。
秉著不重復(fù)造輪子的原則(其實(shí)就是懶),工程直接使用Vue2.0官方腳手架生成,使用最新webpack模板。與標(biāo)準(zhǔn)模板的主要差異:
增加了Sass預(yù)編譯器
增加了Vuex狀態(tài)管理
增加了Axios基礎(chǔ)Ajax工具庫(kù)
新增部分的安裝請(qǐng)參考他們各自的文檔,這里不贅述。
項(xiàng)目結(jié)構(gòu) 模擬需求討論架構(gòu)前我們需要一個(gè)項(xiàng)目需求,這里簡(jiǎn)單模擬一個(gè)。
需求點(diǎn):3個(gè)一級(jí)頁(yè)面,2個(gè)二級(jí)頁(yè)面,底部的tabbar只在一級(jí)頁(yè)面出現(xiàn),首頁(yè)、個(gè)人中心和登錄頁(yè)面是未登錄也可以進(jìn)入;財(cái)務(wù)和編輯個(gè)人信息是只有登錄用戶可見(jiàn),簡(jiǎn)單原型如下:
下面不討論腳手架生成的部分目錄,只聚焦src開(kāi)發(fā)目錄,依據(jù)原型我們可以大致規(guī)劃出下面的目錄:
├── build ├── config ├── dist ├── src 開(kāi)發(fā)目錄 │ ├── api 公共api集 │ │ ├── axiosConfig.js axios實(shí)例配置 | | └── index.js 公共api集入口 │ ├── assets 資源目錄 │ │ ├── images 圖片 │ │ ├── scripts 第三方腳本 | | └── styles 基礎(chǔ)樣式庫(kù) │ ├── components 公共組件 │ │ ├── common 一般通用組件 │ │ ├── form 表單通用組件 │ │ └── popup 彈出類通用組件 │ │── config 項(xiàng)目配置 │ │ ├── dev.env.js 開(kāi)發(fā)模式配置 │ │ ├── env.js 一般配置 │ │ ├── modules.js 模塊配置 │ │ └── prod.env.js 生產(chǎn)模式配置 │ │── mixin 用于vue文件混合的模板 │ │── modules 模塊 │ │ ├── finance 財(cái)務(wù)模塊 │ │ │ ├── components 財(cái)務(wù)模塊私有組件 │ │ │ │ └── FinanceIndexItem.vue 財(cái)務(wù)模塊首頁(yè)里的條目項(xiàng) │ │ │ ├── pages 財(cái)務(wù)模塊頁(yè)面 │ │ │ │ └── FinanceIndex.vue 財(cái)務(wù)模塊首頁(yè) │ │ │ ├── api.js 模塊api集 │ │ │ ├── index.js 模塊入口 │ │ │ ├── Layout.vue 模塊承載頁(yè) │ │ │ └── router.js 模塊內(nèi)路由 │ │ ├── home 首頁(yè)模塊(子目錄同上) │ │ └── user 用戶模塊(子目錄同上) │ │── pages 公共頁(yè)面 │ │ ├── Success.vue 公共狀態(tài)管理模塊 │ │ └── NotFound.vue 用戶模塊(子目錄同上) │ ├── router 路由管理 │ ├── store 公共狀態(tài)管理 │ │ ├── modules 公共狀態(tài)管理模塊 │ │ │ ├── com.js 通用狀態(tài) │ │ │ └── user.js 用戶狀態(tài) │ │ └── index.js 公共狀態(tài)管理入口 │ └── utils 基礎(chǔ)工具 └── static一些規(guī)范約定
根據(jù)本人個(gè)人開(kāi)發(fā)經(jīng)驗(yàn)總結(jié)的規(guī)范,不代表必須這么做。
所有vue組件都以大寫(xiě)字面開(kāi)頭的駝峰命名法命名,這樣保持到模板代碼上,可以便于區(qū)分開(kāi)html的原生標(biāo)簽;
人為劃分vue組件為“頁(yè)面”和“頁(yè)面上的組件”,原則上“頁(yè)面上的組件”不發(fā)請(qǐng)求,不改變公共狀態(tài),全部通過(guò)事件交由“頁(yè)面”完成,本人更傾向用˙集中管理。(其實(shí)vue中并沒(méi)有頁(yè)面概念);
各個(gè)模塊,包括路由管理、公共狀態(tài)管理、接口集等都在目錄下有個(gè)index.js的入口文件,方便引用;
基礎(chǔ)工具內(nèi)的工具使用函數(shù)式編程,做到可移植,不要對(duì)本項(xiàng)目產(chǎn)生依賴;
資源圖片只在項(xiàng)目中保留小圖(就是會(huì)被webpack處理成base64那些),大圖應(yīng)使用cdn,可以動(dòng)態(tài)獲取也可以把地址寫(xiě)到一個(gè)腳本里;
使用eslint使js代碼符合Airbnb規(guī)范。
低耦合模塊化開(kāi)發(fā)項(xiàng)目過(guò)程中常遇到要把原來(lái)的項(xiàng)目分開(kāi)部署,或是組件間耦合、或是多人開(kāi)發(fā)時(shí)組件沖突等問(wèn)題。本人提出的解決辦法是將項(xiàng)目細(xì)分成模塊進(jìn)行開(kāi)發(fā),每個(gè)模塊由若干相關(guān)“頁(yè)面”組成,擁有私有組件、路由、api等,如示例所示:劃分了三個(gè)模塊,首頁(yè)模塊、財(cái)務(wù)模塊、用戶模塊。
【小結(jié)】這種方案的核心就是要將太過(guò)零散的組件(頁(yè)面)聚合成模塊,每個(gè)模塊都有一定遷移性,互不耦合,實(shí)現(xiàn)按需打包,并且在代碼分割上比單純的分頁(yè)面加載更加靈活可控。Layout模塊承載頁(yè)
這個(gè)是為了讓開(kāi)發(fā)這個(gè)模塊的程序員有類似根組件
一般來(lái)說(shuō)它只是個(gè)空的路由跳轉(zhuǎn)頁(yè),當(dāng)然你把模塊的公共數(shù)據(jù)放這里也可以的,在子路由就能this.$parent拿到數(shù)據(jù),可以當(dāng)成子路由間的bus使用,如下以示例的user模塊為例:
模塊內(nèi)路由
模塊內(nèi)路由最后都會(huì)被導(dǎo)入總路由中,不要以為只是簡(jiǎn)單合并了文件,這里的設(shè)計(jì)也跟Layout模塊承載頁(yè)有關(guān),
下面以u(píng)ser模塊為例,我們把個(gè)人中心、登錄和修改個(gè)人信息這三個(gè)頁(yè)面歸為user模塊,路由規(guī)劃如下。
個(gè)人中心:/user
登錄:/user/login
修改個(gè)人信息:/user/userInfo
其中由于“個(gè)人中心”是一級(jí)頁(yè)面,需求要求底部有tabBar,所以使它只能是一級(jí)路由。
接下來(lái)你會(huì)發(fā)現(xiàn)Layout模塊承載頁(yè)的路由路勁也是"/user",這里不用擔(dān)心會(huì)亂,因?yàn)槁酚晒芾硎前错樞蚱ヅ涞模劣跒槭裁匆窂揭粯樱@只是為了滿足路由規(guī)劃,讓路徑好看而已。
// 通用的tabbar import IndexTabBar from "@/components/common/IndexTabBar"; // 模塊內(nèi)的頁(yè)面 import UserIndex from "./pages/UserIndex"; import UserLogin from "./pages/UserLogin"; import UserInfo from "./pages/UserInfo"; export default [ // 一級(jí)路由 { name: "userIndex", path: "/user", meta: { title: "個(gè)人中心", }, components: { default: UserIndex, footer: IndexTabBar, }, }, { path: "/user", // 這里分割子路由 component: () => import("./layout.vue"), children: [ // 二級(jí)路由 { name: "userLogin", path: "login", meta: { title: "登錄", }, component: UserLogin, }, { name: "userInfo", path: "info", meta: { title: "修改個(gè)人信息", requiresAuth: true, }, component: UserInfo, }, ], }, ];
模塊承載頁(yè)以懶加載的形式component: () => import("./layout.vue")引入,這會(huì)使webpack在此處分割代碼,也就是說(shuō)進(jìn)入模塊內(nèi)是需要再此請(qǐng)求的,可以減少首次加載的數(shù)據(jù)量,提高速度。
官方關(guān)于懶加載的文檔
這里你會(huì)發(fā)現(xiàn)后續(xù)的子路由,又是以直接引入的方式加載,也就是說(shuō)整個(gè)模塊會(huì)一起加載,實(shí)現(xiàn)了分模塊加載。
這與簡(jiǎn)單的分頁(yè)面加載不同,分頁(yè)面加載一直有個(gè)難點(diǎn),就是分割的量比較難把握(太多會(huì)增加請(qǐng)求次數(shù),太少又降低了速度),而分模塊可以將相關(guān)頁(yè)面一起加載(跟提高緩存命中率很像),可以更靈活的規(guī)劃我們的加載,最終效果:
用戶進(jìn)入應(yīng)用,首頁(yè)的三個(gè)頁(yè)面(有tabbar的)就已經(jīng)加載完畢,這時(shí)點(diǎn)擊哪個(gè)tabbar按鈕都能流暢;
當(dāng)用戶進(jìn)入某個(gè)頁(yè)面內(nèi)的子頁(yè)面,會(huì)產(chǎn)生一次請(qǐng)求;
這時(shí)整個(gè)模塊的頁(yè)面都加載完(不一定要全部),用戶在這個(gè)模塊內(nèi)又能流暢訪問(wèn)。
模塊api集這個(gè)設(shè)計(jì)跟模塊內(nèi)路由類似,目的也是為了按需加載和隔離全局。
下面也是以u(píng)ser模塊的模塊api集為例,可以發(fā)現(xiàn)和路由有一些不同就是這里為了防止模塊跟全局耦合,運(yùn)用函數(shù)式編程思想(類似于依賴注入),將全局的axios實(shí)例作為函數(shù)參數(shù)傳入,再返回出一個(gè)包含api的對(duì)象,這個(gè)導(dǎo)出的對(duì)象將會(huì)被以模塊名命名,合并到全局的api集中。
export default function (axios) { return { postHeadImg(token, userId, data) { const options = { method: "post", name: "換頭像", url: "/data/user/updateHeadImg", headers: { token, userId, }, data, }; return axios(options); }, postProduct(token, userId, data) { const options = { method: "post", name: "提交產(chǎn)品選擇", url: "/product/opt", headers: { token, userId, }, data, }; return axios(options); }, }; }模塊入口
為了方便引用,每個(gè)模塊目錄下都有一個(gè)index.js,引入模塊的時(shí)候可以省略,node會(huì)自動(dòng)讀這個(gè)文件。
還是以u(píng)ser模塊為例,這里主要是引入模塊專屬api和模塊內(nèi)路由,并定義了模塊的名字,這個(gè)名字是后面掛載專屬api是時(shí)候用的。
import api from "./api"; import router from "./router"; export default { name: "user", api, router, };按需打包
示例中config目錄下有個(gè)modules.js文件是指定打包需要的模塊,測(cè)試一下打包不同數(shù)量的模塊,會(huì)發(fā)現(xiàn)產(chǎn)品文件大小會(huì)改變,這就證明了已經(jīng)實(shí)現(xiàn)按需打包。
至于路由和api集的子模塊整合實(shí)現(xiàn),后面會(huì)提到。
import home from "@/modules/home"; import finance from "@/modules/finance"; import user from "@/modules/user"; export default [ home, finance, user ]api集的配置
【背景】示例項(xiàng)目模擬常見(jiàn)的接口約定,服務(wù)器與應(yīng)用交互有兩個(gè)自定義頭部:token和userId。token是權(quán)限標(biāo)識(shí)符,幾乎全部api都需要帶上,為了防CSRF;userId是登錄狀態(tài)標(biāo)識(shí)符,有些需要登錄狀態(tài)才能使用的接口才需要帶上,這兩個(gè)標(biāo)識(shí)符都有有效期。本示例暫不考慮自動(dòng)續(xù)期的機(jī)制。
在api管理方面本人比較喜歡集中管理接口和配置,但發(fā)起請(qǐng)求和請(qǐng)求回調(diào)傾向與每個(gè)接口多帶帶處理。
導(dǎo)出axios實(shí)例axios是比較流行的ajax的promise封裝。axios官方文檔
本人推薦在全局保留唯一的axios實(shí)例,所有的請(qǐng)求都使用這個(gè)公共實(shí)例發(fā)起,實(shí)現(xiàn)配置的統(tǒng)一。
示例項(xiàng)目的在api文件夾下的axiosConfig.js就是axios的配置,主要是導(dǎo)出一個(gè)符合項(xiàng)目設(shè)置的實(shí)例,并進(jìn)行一些攔截器設(shè)置。
【PS】至于為什么到導(dǎo)出實(shí)例而不是直接修改axios默認(rèn)值?
這是為了預(yù)防某些特例情況下公共實(shí)例無(wú)法滿足需求,需要多帶帶配置axios的情況,所以為了不污染原始的axios默認(rèn)值,不推薦修改默認(rèn)值。
// 引入axios包 import axios from "axios"; // 引入環(huán)境配置 import env from "../config/env"; // 引入公共狀態(tài)管理 import store from "../store/index"; // 全局默認(rèn)配置 const myAxios = axios.create({ // 跨域帶cookie withCredentials: true, // 基礎(chǔ)url baseURL: `${env.apiUrl}/${env.apiVersion}`, // 超時(shí)時(shí)間 timeout: 12000, }); // 請(qǐng)求發(fā)起前攔截器 myAxios.interceptors.request.use((_config) => { // ... return config; }, () => { // 異常處理 }); // 響應(yīng)攔截器 myAxios.interceptors.response.use((response) => { // ... }, (error) => { // 異常處理 return Promise.reject(error); }); export default myAxios;公共api集
項(xiàng)目的所有公共api都會(huì)編寫(xiě)到這里,實(shí)現(xiàn)集中化管理,最后公共api集會(huì)掛載到vue根實(shí)例下,使用this.$api就可以方便的訪問(wèn)。
由于token和userId不是必須頭部,這里我推薦每個(gè)接口函數(shù)都多帶帶處理,按需傳入,這樣api函數(shù)也能更加清晰。
給每個(gè)接口起名字,是為了后續(xù)取消請(qǐng)求所設(shè)計(jì)的。
整體思路:先定義公共api,再將模塊內(nèi)api(按需)掛載進(jìn)來(lái),最后導(dǎo)出api集。
// 引入已經(jīng)配置好的axios實(shí)例 import axios from "./axiosConfig"; // 引入模塊 import modules from "../config/modules"; const apiList = { // 獲取token不需要 getToken() { const options = { method: "post", name: "獲取token", url: "/token/get", }; return axios(options); }, loginWithName(token, data) { const options = { method: "post", name: "用戶名密碼登錄", url: "/data/user/login4up", headers: { token, }, data, }; return axios(options); }, postHeadImg(token, userId, data) { const options = { method: "post", name: "換頭像", url: "/data/user/updateHeadImg", headers: { token, userId, }, data, }; return axios(options); }, }; // 使每個(gè)模塊里的api集掛載到以模塊名為名的命名空間下 modules.forEach((i) => { Object.assign(apiList, { [i.name]: i.api(axios), }); }); export default apiList;路由管理配置 導(dǎo)入模塊內(nèi)路由
使用示例中用router文件夾下的index.js配置全局路由,api集類似實(shí)現(xiàn)集中化管理,導(dǎo)出路由實(shí)例會(huì)掛載到vue根實(shí)例下,使用this.$router就可以方便的訪問(wèn)。
配置參考官方文檔,這里主要提的一點(diǎn)是,模塊內(nèi)路由的整合,見(jiàn)實(shí)例代碼段。
Vue.use(Router); // 路由配置 const routerConfig = { routes: [ { path: "/", meta: { title: env.appName, }, redirect: { name: "home" }, }, { name: "success", path: "/success", meta: { title: "成功", }, component: Success, }, { path: "*", component: NotFound, }, ], }; // 將模塊內(nèi)的路由拼接到全局 modules.forEach((i) => { routerConfig.routes = routerConfig.routes.concat(i.router); }); const router = new Router(routerConfig);在路由鉤子函數(shù)中處理標(biāo)題和權(quán)限
路由的鉤子函數(shù)有很多妙用,這里列舉了一些例子。
路由元信息meta可以自定義需要的數(shù)據(jù),相當(dāng)于給路由一個(gè)標(biāo)記,然后在router.afterEach鉤子函數(shù)中可以讀取到并進(jìn)行處理。
回顧上面示例的模塊內(nèi)路由,meta中定義了title(標(biāo)題)和requiresAuth(是否要登錄狀態(tài)),這就會(huì)在這里體現(xiàn)出用處。把登錄權(quán)限設(shè)置在這里判斷是為了防止用戶進(jìn)入某些需要權(quán)限的“頁(yè)面”。
router.beforeEach((to, from, next) => { // 關(guān)閉公共彈框 if (window.loading) { window.loading.close(); } // 設(shè)置微信分享(如果有) wxShare({ title: "哇哈哈", desc: "在路由鉤子函數(shù)中處理標(biāo)題和權(quán)限", link: env.shareBaseUrl, imgUrl: env.shareBaseUrl + "/images/shareLogo.png" }); // 設(shè)置標(biāo)題 document.title = to.meta.title ? to.meta.title : "示例"; // 檢查登錄狀態(tài) if (to.meta.requiresAuth) { // 目標(biāo)路由需要登錄狀態(tài) // ... } next(); });自動(dòng)化管理權(quán)限標(biāo)識(shí)符(token)
權(quán)限標(biāo)識(shí)符的特點(diǎn)就是幾乎每個(gè)鏈接都要帶上,需要維護(hù)有效期,為了不浪費(fèi)服務(wù)器資源還需要持久化并保證請(qǐng)求唯一。
本人比較推薦使用公共狀態(tài)管理vuex進(jìn)行自動(dòng)化管理,減少代碼編寫(xiě)時(shí)的顧慮。
示例中公共狀態(tài)中的com模塊里有tokenObj和waitToken兩個(gè)字段,其中tokenObj包含了token和過(guò)期時(shí)間,waitToken是一個(gè)標(biāo)記是否當(dāng)前在獲取token的布爾值。
【PS】為什么要token保證唯一一次請(qǐng)求?
常見(jiàn)的場(chǎng)景:當(dāng)用戶進(jìn)入應(yīng)用,這時(shí)候token要么沒(méi)有要么已過(guò)期,這時(shí)頁(yè)面需要并發(fā)兩個(gè)ajax請(qǐng)求,由于都沒(méi)有token,不唯一化處理的話,會(huì)同時(shí)先發(fā)起兩個(gè)token請(qǐng)求,這樣首先是浪費(fèi)了請(qǐng)求資源,其次由于是異步請(qǐng)求,不能保證兩次token的順序,如果服務(wù)器對(duì)token管理較嚴(yán)格則會(huì)出問(wèn)題。
由于獲取token是異步操作,所以getToken寫(xiě)在actions中,把主要過(guò)程包裹成立即執(zhí)行函數(shù),并通過(guò)waitToken判斷是否要等待,如果要等待就隔一段時(shí)間再檢查,這樣就保證了并發(fā)請(qǐng)求時(shí),token能唯一。
const actions = { // needToRegain是為了特殊條件下強(qiáng)制獲取使用 getToken({ commit, state: _state }, needToRegain) { return new Promise((resolve, reject) => { (function main() { // 如果waitToken為真即表示發(fā)起了請(qǐng)求但還未回應(yīng) if (_state.waitToken) { console.log("等待token"); setTimeout(() => { main(); }, 1000); return; } // 是否過(guò)期標(biāo)記 let isExpire = false; // 提取現(xiàn)有的tokenObj let tokenObj = { ..._state.tokenObj, }; // 如果沒(méi)有token就從本地存儲(chǔ)中讀取 if (!tokenObj.token) { tokenObj = JSON.parse(localStorage.getItem("tokenObj")); // 如果本地有tokenObj會(huì)順便添加到狀態(tài)管理 if (tokenObj) { commit("setTokenObj", tokenObj); } } // token是否過(guò)時(shí) if (tokenObj && tokenObj.token) { isExpire = new Date().getTime() - tokenObj.expireTime > -10000; } // 綜合判斷是否需要獲取token if (!tokenObj || !tokenObj.token || isExpire || needToRegain) { commit("setWaitToken", true); api.getToken().then((res) => { // 檢查返回的數(shù)據(jù) const checkedData = connect.dataCheck(res); if (checkedData.isDataReady) { const newTokenObj = { token: checkedData.data.token, expireTime: new Date().getTime() + (checkedData.data.expire_time * 1000), }; // 設(shè)置TokenObj會(huì)順便保留一份到本地存儲(chǔ) commit("setTokenObj", newTokenObj); commit("setWaitToken", false); console.log("獲取token成功"); resolve(newTokenObj.token); } else { commit("setWaitToken", false); console.error("獲取token失敗"); reject(checkedData.msg); } }).catch((err) => { window.toast("網(wǎng)絡(luò)錯(cuò)誤"); commit("setWaitToken", false); reject(err); }); } else { console.log("token已存在,直接返回"); resolve(tokenObj.token); } }()); }); }, };token在請(qǐng)求代碼中使用
將需要token的api函數(shù)套在getToken的回調(diào)中,就能方便的使用,不用再擔(dān)心token是否過(guò)期。
const sendData = { mobile: this.formData1.mobile, }; this.$store.dispatch("getToken").then((token) => { this.$api.sendSMS(token, sendData).then((res) => { const checkedData = this.$connect.dataCheck(res); if (checkedData.isDataReady) { window.toast("驗(yàn)證碼已發(fā)送,請(qǐng)查收短信"); } else { window.toast("驗(yàn)證碼發(fā)送失敗"); } }).catch(() => { window.toast("網(wǎng)絡(luò)錯(cuò)誤"); }); });
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/52094.html
摘要:接上篇議題合理的架構(gòu)討論上傳送門(mén)。處理思路如下使用上面定義的方法獲取如果能獲取到則說(shuō)明有有效的,則時(shí)候即可跳轉(zhuǎn)到目標(biāo)頁(yè)如果獲取到空字符串,則說(shuō)明無(wú)效或不存在,跳轉(zhuǎn)至登錄頁(yè)面。 接上篇《【Geek議題】合理的VueSPA架構(gòu)討論(上)》傳送門(mén)。 自動(dòng)化維護(hù)登錄狀態(tài) 登錄狀態(tài)標(biāo)識(shí)符跟token類似,都是需要自動(dòng)維護(hù)有效期,但也有些許不同,獲取過(guò)程只在用戶登錄或注冊(cè)的時(shí)候,不需要自動(dòng)獲取。 ...
摘要:接上篇議題合理的架構(gòu)討論上傳送門(mén)。處理思路如下使用上面定義的方法獲取如果能獲取到則說(shuō)明有有效的,則時(shí)候即可跳轉(zhuǎn)到目標(biāo)頁(yè)如果獲取到空字符串,則說(shuō)明無(wú)效或不存在,跳轉(zhuǎn)至登錄頁(yè)面。 接上篇《【Geek議題】合理的VueSPA架構(gòu)討論(上)》傳送門(mén)。 自動(dòng)化維護(hù)登錄狀態(tài) 登錄狀態(tài)標(biāo)識(shí)符跟token類似,都是需要自動(dòng)維護(hù)有效期,但也有些許不同,獲取過(guò)程只在用戶登錄或注冊(cè)的時(shí)候,不需要自動(dòng)獲取。 ...
摘要:下面也是以模塊的模塊集為例,可以發(fā)現(xiàn)和路由有一些不同就是這里為了防止模塊跟全局耦合,運(yùn)用函數(shù)式編程思想類似于依賴注入,將全局的實(shí)例作為函數(shù)參數(shù)傳入,再返回出一個(gè)包含的對(duì)象,這個(gè)導(dǎo)出的對(duì)象將會(huì)被以模塊名命名,合并到全局的集中。 前言 web前端發(fā)展到現(xiàn)代,已經(jīng)不再是嚴(yán)格意義上的后端MVC的V層,它越來(lái)越向類似客戶端開(kāi)發(fā)的方向發(fā)展,已獨(dú)立擁有了自己的MVVM設(shè)計(jì)模型。前后端的分離也使前端人...
摘要:同源策略年,同源政策由公司引入瀏覽器。標(biāo)簽不受同源策略限制,但只能發(fā)起請(qǐng)求。這一行為使得不同域的特定文檔可以讀取該屬性值,因此可以繞過(guò)同源策略并使跨域消息通信成為可能。 前言 現(xiàn)在cross-origin resource sharing(跨域資源共享,下簡(jiǎn)稱CORS)已經(jīng)十分普及,算上IE8的不標(biāo)準(zhǔn)兼容(XDomainRequest),各大瀏覽器基本都已支持,當(dāng)年為了前后端分離、if...
摘要:同源策略年,同源政策由公司引入瀏覽器。標(biāo)簽不受同源策略限制,但只能發(fā)起請(qǐng)求。這一行為使得不同域的特定文檔可以讀取該屬性值,因此可以繞過(guò)同源策略并使跨域消息通信成為可能。 前言 現(xiàn)在cross-origin resource sharing(跨域資源共享,下簡(jiǎn)稱CORS)已經(jīng)十分普及,算上IE8的不標(biāo)準(zhǔn)兼容(XDomainRequest),各大瀏覽器基本都已支持,當(dāng)年為了前后端分離、if...
閱讀 973·2021-11-25 09:43
閱讀 2298·2019-08-30 15:55
閱讀 3160·2019-08-30 15:44
閱讀 2059·2019-08-29 16:20
閱讀 1459·2019-08-29 12:12
閱讀 1614·2019-08-26 12:19
閱讀 2289·2019-08-26 11:49
閱讀 1718·2019-08-26 11:42