背景
vue-cli項目。路由是hash模式。需要授權的場景有:項目入口處(App.vue),指定頁面(創建時、methods 方法內);可以攜帶參數
思路
由於hash模式# 號的存在,授權后鏈接會被擾亂。所以 我希望在 授權前 將重定向的鏈接 即 redirect_uri 改為沒有# 的url。然后在 項目入口處 進行 url 重置,將其改回到 丑陋的 帶#鏈接。
即:兩步操作
1、授權前 將redirect_uri 改為沒有# 的url
2、項目入口處,將沒有#的url改回到 帶#的url,跳到指定頁面。
主要代碼
1、授權前,redirect_uri 重置
這里會將當前頁面的原有參數信息、額外參數、codepath參數 作為 redirect_uri 的新參數。其中codepath是 用來指定 跳轉頁面的,通常為 授權發起頁。
/** * 開始設置頁面鏈接,進行code 授權重定向 * * @param scope 授權作用域 * @param path 授權所在頁面 path * @param extraPm 額外參數,需要在 配置中 進行參數配置 * @returns {string} */ get_codeV3(scope, path, extraPm={}) { if (process.env.NODE_ENV === 'development' && config.isMockWeChat) return '0713eFVW0AmFP12kGVTW0oGDVW03eFV2' let homeUrl = '', searchOb = {}, searchstr = '' let oriUrls = window.location.href.split('?') let baseShareURl = window.location.origin + window.location.pathname homeUrl = baseShareURl if (oriUrls.length > 1) { let searchUrls = oriUrls[1].split('#') let searchUrlReal = searchUrls[0] searchOb = qs.parse(searchUrlReal) let {code} = searchOb if (code) delete searchOb.code } searchOb.codepath = path Object.assign(searchOb, extraPm) searchstr = `?${qs.stringify(searchOb)}` homeUrl += searchstr let redirect_uri = encodeURIComponent(homeUrl); let response_type = 'code'; // 應用授權作用域, // snsapi_base (不彈出授權頁面,直接跳轉,只能獲取用戶openid), // snsapi_userinfo (彈出授權頁面,可通過openid拿到昵稱、性別、所在地。並且, 即使在未關注的情況下,只要用戶授權,也能獲取其信息 ) // 重定向后會帶上state參數,開發者可以填寫a-zA-Z0-9的參數值,最多128字節 let state = ''; let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=${response_type}&scope=${scope}&state=${state}#wechat_redirect`; window.location.href = url; }
2、鏈接前置判斷
在項目入口處,發現有 codepath 參數,即 將該鏈接視為 授權后的redirect_uri 鏈接。進行頁面重定向,跳轉到 codepath 指定頁面
/** * 頁面重定向(授權)-確保頁面鏈接正常 * 支持多參、無參、指定頁面
* code 在 返回的search 里 * @returns {{needRedirect: boolean, homeUrl: string, search: {}}} */ urlResetForWxCode: function () { //需要重定向時:codepath 參數 與 code 參數同在。 let needRedirect = false, homeUrl = '', searchOb = {}, searchstr = '' let oriUrls = window.location.href.split('?') let baseShareURl = window.location.origin + window.location.pathname homeUrl = baseShareURl if (oriUrls.length > 1) { let searchUrls = oriUrls[1].split('#') let searchUrlReal = searchUrls[0] let searchObReal = {} searchOb = qs.parse(searchUrlReal) let { codepath } = searchOb needRedirect = codepath if (codepath) { config.platform.wxCode[codepath].forEach(item => searchObReal[item] = searchOb[item]) if (config.platform.wxCode[codepath].length) searchstr = `?${qs.stringify(searchObReal)}` homeUrl += `#${codepath}` + (searchstr.length > 1 ? searchstr : '') } } return { needRedirect, homeUrl, search: searchOb } }
// 配置信息
config = { platform: { wxCode: {'/': ['hello', 'yiha'], '/spe': ['spp']}, // 微信授權-需要授權的頁面: [頁面用到的參數]
}
}
使用
1、授權發起位置通常有 項目入口處、頁面create 時,頁面 指定方法內。
if (!storage.getToken()) {// code 授權標志 保存在localstorage。 wx_jssdk.get_codeV3('snsapi_userinfo', '/') return }
2、項目入口處進行前置判斷
// App.vue
created(){ // 可以在項目入口處 進行code授權 if (!storage.getToken()) {// code 授權標志 保存在localstorage。 wx_jssdk.get_codeV3('snsapi_userinfo', '/') return } // 項目只要用到授權,則需要進行重定向判斷。 let {needRedirect, homeUrl, search} = browserUtil.urlResetForWxCode() if (needRedirect) { storage.setToken({code: search.code}) // 保存code window.location.href = homeUrl } }
寫在最后
想着盡量能夠做到配置化、可擴展,目前很low。湊合用吧😄
配置化的體現:
鏈接前置判斷方法內,組裝鏈接參數時,我是只拿配置信息里的存在的參數。(方法里飄紅的代碼)。這是為了參數可控,避免不必要的bug。
可擴展的體現:
在redirect_uri 重置方法 參數里,有一個額外參數,原本 想着只截取授權發起頁的原始search參數就好了。但一想 會不會有這樣的使用場景:
表單提交頁,在提交時 才去發起授權。這樣的話 可能授權后 原表單信息已丟失,即需要重新再來;體驗並不好。那么可不可以 將表單數據作為 授權時的一部分參數,然后在授權成功后,頁面重新create時 檢測到有表單數據時 直接提交。(當然,你也可以通過local保存數據來實現這個功能,或者其他)
注:該額外參數 也需要在配置里注明,不然 前置判斷里 會不予理會。