單頁應用應該如何解決微信授權登錄的尷尬跳轉?後退無法返回?
主要遇到的問題就是
先進入單頁應用,一邊渲染頁面一邊判斷用戶有沒有登錄,當判斷到沒有登錄時異步數據請求已經發送出去了,然後要跳轉到微信授權頁面,這樣就浪費了一次網絡請求且用戶可能要去點擊這個數據了結果...跳走了!在授權成功後用戶點擊後退再次進行授權有沒有???
本文主要講述
對於單頁應用應該在哪個階段獲取微信授權?
只考慮網站完全依賴微信授權登錄,一進入就要以授權的身份進入
基本思路
核心是需要有個author.vue 叫它授權中間頁好了
vue開發過程中的一些點子
由於我的業務是完全依賴微信授權登錄的,也就是用戶一進來就應該是已經完成授權的
爲了避免讓用戶明顯感覺到先進入網站然後又跳轉到微信授權頁面
我們從vue-router下手
基本實現思路是:
- 無論使用哪個url進入網站都會先觸發router.beforeEach鉤子
- 在router.beforeEach鉤子中判斷用戶當前登錄狀態
- 若沒有登錄則保存用戶進入的url並跳轉到author授權頁面
- author授權頁面完成微信授權以及token的寫入實現用戶登錄
- 獲取前面保存的用戶進入url並跳轉
經過這樣一個流程,用戶感覺到的就是,無論從哪個url進入SPA,都會先顯示author頁面,然後再進入自己想要進入的頁面,而不是先進入自己想要進入的頁面再閃到author頁面,這樣不僅節省了資源也提升了用戶體驗,更重要的一點是!我們的項目多了一個廣告頁面(無語...)!!!
先貼上我的實現代碼
用戶信息保存在Vuex中
// holdno是我自己定義的一個工具集 裏面有各種操作方法
router.beforeEach((to, from, next) => {
if(!store.state.user.id && to.path != '/author'){
// 第一次進入項目
holdno.cookie.set('beforeLoginUrl', to.fullPath) // 保存用戶進入的url
next('/author')
return false
}
next()
})
下面來看一下author頁面的處理邏輯
created () {
// 檢測會員有沒有登錄
if(!holdno.cookie.get('user')){
let ua = window.navigator.userAgent.toLowerCase()
if(ua.match(/MicroMessenger/i) == 'micromessenger'){
// 跳轉到微信授權頁面
window.location.href = this.webUrl + '/Wap/User/getOpenid'
}
}else{
// 如果有token 但是vuex中沒有用戶登錄信息則做登錄操作
this.login()
}
},
methods: {
login () {
let url = this.webUrl + '/Wap/User/info'
// 通過cookie中保存的token 獲取用戶信息
this.$http.get(url).then(response => {
response = response.body
if(response){
// 保存用戶登錄狀態(Vuex)
this.$store.commit('user', response)
setTimeout(() => {
this.goBeforeLoginUrl() // 頁面恢復(進入用戶一開始請求的頁面)
}, 2000)
}else{
this.$alert('服務器擼貓去惹 :(', 'wrong')
if(holdno.cookie.get('user')){
// 跳轉到微信授權頁面
window.location.href = this.webUrl + '/Wap/User/getOpenid'
}
}
})
}
}
上述代碼中 window.location.href = this.webUrl + '/Wap/User/getOpenid'
這一段是後端請求微信授權登錄接口的地址,在後端獲取到用戶信息及openid後再次跳轉到author頁面而不是直接定向到用戶想要請求的位置,這樣做的原因很簡單。
如果用戶跳轉到授權頁面,由後端獲取用戶信息並保存好登錄狀態,重定向到用戶請求的頁面,這時只要用戶點擊一下後退,所有的邏輯重新再來一遍有沒有?作爲一個不懂技術的用戶,應該也是很鬱悶,爲什麼後退還是跳回來了呢???
所以獲取用戶信息後再次重定向到author頁面,由author做一箇中間頁檢測到獲取到用戶信息後在前端做一個跳轉,也就是代碼中的this.goBeforeLoginUrl()(跳轉到登錄前的url ...哈哈哈),這時候用戶再點擊後退就會退回到author頁面而不是後端獲取用戶openid的url,但真的會再次顯示author頁面給用戶嗎?並不會,回看我們路由鉤子的定義:
router.beforeEach((to, from, next) => {
if(to.path == '/author' && store.state.user.id){
// 用戶使用後退返回到授權頁,則默認回到首頁
next('/index')
return false
}
...
})
後面部分這裏不重要,展示出來的則是關鍵部分,在再次跳轉至author前,路由鉤子被觸發,檢測到即將進入的頁面to.path == '/author'成立同時剛纔在this.login()中做了this.$store.commit('user', response)操作,所以if條件成立頁面被直接跳轉至'/index'首頁,所以在這一個流程中,用戶並沒有再次看到授權頁面,而是直接返回到了首頁,是不是很完美!
this.goBeforeLoginUrl()
// 登錄後跳轉方法
Vue.prototype.goBeforeLoginUrl = () => {
let url = holdno.cookie.get('beforeLoginUrl')
if(!url || url.indexOf('/author') != -1){
router.push('/index')
}else{
if(url == '/'){
url = '/index'
}
router.push(url)
holdno.cookie.set('beforeLoginUrl', '')
}
}
看完整個流程,author只講到邏輯處理,但它畢竟是一個頁面,也是要展示給用戶看的,只處理邏輯的話難道白花花的一片show給用戶嗎?當然不是!想必大家都瞭解app在初次啓動時都有一個廣告頁吧,我們完全可以把author授權中間頁包裝成一個廣告頁,在用戶瀏覽花哨的圖片(廣告)時默默完成授權登錄的處理 :)
Vue微信授權
大概的授權邏輯是:
-
路由攔截:
利用Vue路由攔截,判斷用戶登錄狀態(後面向後臺請求的時候,讓後臺返回),如果是登錄狀態就next(),否則去授權頁(這裏提示一下,我弄了一個空白頁用來授權用的author.vue)
下面 -
獲取code:
前端先獲取當前地址,傳給後臺,後臺拿到你的當前地址,通過微信提供的接口,返回一個拼接上參數(appid,redirect_uri…)的微信端授權地址,這時候前端跳轉該地址顯示微信授權頁面,用戶授權之後拿到帶有code的地址。 -
獲取openid:
截取地址獲取code傳遞給後臺,後臺拿着code向微信服務器請求,獲取access_token和openod並且存到數據庫,返回有用的數據。