【感謝原文:https://segmentfault.com/a/1190000009493199】
SPA單頁應用中微信授權登錄的一點思路
單頁應用應該如何解決微信授權登錄的尷尬跳轉?后退無法返回?
主要遇到的問題就是
先進入單頁應用,一邊渲染頁面一邊判斷用戶有沒有登錄,當判斷到沒有登錄時異步數據請求已經發送出去了,然后要跳轉到微信授權頁面,這樣就浪費了一次網絡請求且用戶可能要去點擊這個數據了結果...跳走了!在授權成功后用戶點擊后退再次進行授權有沒有???
本文主要講述
對於單頁應用應該在哪個階段獲取微信授權?
只考慮網站完全依賴微信授權登錄,一進入就要以授權的身份進入
基本思路
核心是需要有個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(to.path == '/author' && store.state.user.id){ // 用戶使用后退返回到授權頁,則默認回到首頁 next('/index') return false } if((!holdno.cookie.get('user') || !store.state.user.id) && to.path != '/author'){ // 第一次進入項目 holdno.cookie.set('beforeLoginUrl', to.fullPath) // 保存用戶進入的url next('/author') return false }else if(!store.state.user.id && to.path != '/author'){ // 之前有獲取過授權 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授權中間頁包裝成一個廣告頁,在用戶瀏覽花哨的圖片(廣告)時默默完成授權登錄的處理 :)
至於這個圖這么丑...額 只是想臨時做個示例,所以...
大概就是這么個意思 :P
掃碼體驗(demo階段)
希望能有大神交流更優解決方案。