登陆,几乎什么项目都会用到,其重要性不言而喻,而小程序的登陆却一直是为人头疼的一件事,这里我分享下咱们在小程序登陆上的探索
一般的登陆都是经过一个表单,这很正常,但若是在小程序里你也这么作那就有点难以想象了,微信的一键登陆对用户体验有多好你难道不知道?不用是否是脑子有坑?最主要——你要利用微信的生态必须须要用微信的登陆,以获取相关信息来和微信交互,OK,咱们进入正题前端
友情提示一下:wx.login
并不须要点击组件,须要的是wx.getUserInfo
,但一般咱们都会用到UnionID、encryptedData、iv等信息
完成完整的登陆流程,本文主要聚焦的也是这种场景
因此以前直接经过调用API的方式就行不通了,那么问题来了——这个点击按钮要放到哪里?小程序
在须要受权的时候跳到登录页面。这样就解决了上面遇到的不须要受权的时候也被强制受权,但是这样好吗?segmentfault
那就直接放在须要登陆的页面上(这不是漏斗吗?不少读者必定这么想。但想一想看上面那个场景,点评论时只是须要点击下弹出的登陆按钮,并且还假模假样的以微信的口吻提醒你须要登陆,那你会不会登陆?最起码你很愿意登陆,并且来的很忽然,我控几不住本身的手就点了!点了!) 后端
但是这种方式有一个问题微信小程序
应该不少人都能想到:抽离出组件,那怎么保证在须要的页面都有这个组件呢?错杀一千也不能放过一个!把登陆组件集成到共用的父组件,而后在每一个页面都使用。我也建议这么作,由于这个共用的父组件其实又不少用处,例如iPhoneX适配等 api
等等,什么都准备好了,何时须要登陆呢?XX,这个确定是你本身控制的啦。嗯~好吧,咱们来理一理微信
请求接口的时候,嗯~这是你们的共识session
BOSS来了
官方的这张图已经作了很详尽的说明,这里不作赘述
可是看到session_key
了吗?看到官方同时说的了吗app
因此问题又来了
诚如上图
session_key
不失效,只能在每次调用前先使用wx.checkSession
检查是否有效wx.checkSeesion
很是耗时,大约200ms,因此也不能每次接口调用前都使用wx.checkSession
检查是否有效wx.login
,由于可能致使正在进行的其它后端任务session_key失效天啦噜,怎么办?!
经过实践和偶然的发现——官方的示例代码
得知:在使用小程序期间session_key是不会失效的,so,你想到了什么?
先问个问题:你准备用什么方式来存储校验的结果?
。。。
让思考先飞一会
。。。。。。
。。。。。。。。。
。。。。。。。。。。。。
storage吗?固然能够,不过不够完美,为何?由于storage是永久的存储,而session_key的有效期却只是在使用小程序期间,因此你须要在小程序结束后手动重置该状态以从新校验其有效性,那是否是在app的onUnload里重置呢?不是!开发太小程序的应该都知道,那就是结束使用小程序的方式太多,不能保证每种方式都会触发onUnload,例如用户直接销毁了微信进程😳(其实你也能够在app的onShow里搞)那用什么呢?直接用内存啊,借助内存的自动管理来智能管理,因此最终代码应该是这样的
// doRequest.js let wxSessionValid = null // 微信session_key的有效性 // 带鉴权的请求封装 async function doRequestWithCheckAuth() { ... if (typeof wxSessionValid !== 'boolean') { wxSessionValid = await checkWxSession() // 检查微信session是否有效 } if (!wxSessionValid) { await reLogin() // 从新登陆 } wxSessionValid = true // 从新登录后session_key必定有效 ... }
这样是否是看起来比较完美了?嗯~
不知道有没有同窗着急问业务侧的session(自定义的登陆态)怎么没讲?嗯,那如今讲吧
其实很简单,都不想把它做为一部分来说,但既然讲了就必然有我想强调的
校验微信端的session_key略有麻烦,但不该该把它抛给服务端
而放在前端咱们只须要校验两个session的有效性便可,任何一个失效就从新登陆,这是积极主动有效的操做,应该被提倡
OK,基本上梳理的差很少了,就差弹登陆按钮了,这个简单,调用刚才封装的组件的方法就好了嘛,bingo,但是,点完容许后呢?怎么继续用户的操做呢?怎么能让用户的体验不被打断呢?先回放下刚才reLogin的代码
async function reLogin() { // 确保有用户信息 await new Promise(resolve => { // ⚠️注意开头有await!!! wx.getSetting({ success: (res) => { // 若是用户没有受权或者没有必要的用户信息 if (!res.authSetting['scope.userInfo'] || !_.isRealTrue(wx.getStorageSync('userInfoRes').userInfo)) { navToLogin(resolve) // 去提示用户点击登陆按钮,⚠️注意:并把当前的resolve带过去 } else { resolve() // 静默登陆 } } }) }) return new Promise((resolve) => { wx.login({ success: res => { login(res.code).then((jwt) => { resolve(jwt) // resolve jwt }) // 经过code进行登陆 }, fail(err) { wx.showToast({ title: err.errMsg, icon: 'none', duration: 2000 }) } }) }) } function navToLogin(resolve) { /* eslint-disable no-undef */ const pages = getCurrentPages() const page = pages[pages.length - 1] // 当前page page.openLoginModal(resolve) // 打开登陆按钮弹框,并把当前的resolve带过去 }
上面的代码注释里有两个⚠️注意看到没?是的,经过回调的方式😂当用户赞成受权了就继续余下的逻辑,若是被拒绝了,则安利他,再拒绝就终止操做,下次须要受权也会继续弹出受权
有不明白欢迎评论留言指出,我再作说明修改
下一篇文章里会有代码呈现,完整源码之后会放出的,经过wepy搭建的一个框架
下一篇:对api请求封装的探索和总结谢谢