在小程序开发中,授权登录是最常见的操作,因为很多业务是要求用户登录之后才能进行操作,那么这个流程我是怎么设计的呢,下面我就给大家唠一唠。
因为授权操作属于比较基本的功能,而且公共需求比较高,于是我把它放到了 app.js
中。在需要的地方,通过 getApp()
函数拿到 app 实例进行调用即可,使用上还是比较便利的。
下面是 app.js
中核心的代码片段:
{
/**
* 封装一个函数统一获取用户信息,避免直接操作 globalData
*/
getUserInfo() {
return this.globalData.userInfo;
},
/**
* 判断是否登录
*/
checkAuth() {
return new Promise((resolve, reject) => {
const userInfo = this.getUserInfo();
userInfo ? resolve(userInfo) : reject('未登录');
});
},
/**
* 授权登录
* 我为了简单直接用 wx.getUserProfile 进行模拟授权
* 实际的业务情况可能还需要弹出个面板或者跳转到授权页面之类的
*/
auth() {
return new Promise((resolve, reject) => {
wx.getUserProfile({
desc: '授权登录',
success: resolve,
fail: reject,
})
}).then(({ userInfo }) => {
this.globalData.userInfo = userInfo;
});
},
/**
* 保证一定是登录的状态
*/
authed() {
return this.checkAuth().catch(() => {
return this.auth();
});
},
/**
* 退出登录
*/
logoff() {
return new Promise((resolve) => {
this.globalData.userInfo = null;
resolve();
});
},
globalData: {
userInfo: null
}
}
主要的逻辑函数都用流行的 Promise 包裹,避免回调嵌套,组合使用特方便。在实际的业务中我会这样去使用:
{
// tap事件处理
async clickHandler() {
const app = getApp();
// 点击之后,通过 authed() 函数保证用户一定是登录状态
// 通 Promise 链,可以很容易的实现授权之后,自动执行后续的流程
app.authed().then(() => {
// 身份校验通过后调用核心的逻辑 actAction
return this.actAction();
});
},
async actAction() {
// todo 动作响应
console.log('动作响应');
}
}
通过 js
的方式,这样没问题,但我想 Amazing
一下:我能不能在 js
中不调用 authed()
也能实现一样的逻辑 。经过我 3S
钟的思考之后,一激动就拔下了名叫 Tom 的这根头发:
对于有点击行为的元素,我可以设计一个
Auth
组件,专门用来做登录操作,然后将这个组件嵌套在需要有点击行为的元素中。比如:
<button class="submit-btn" bindtap="actAction">点击<Auth/></button>
让这个
Auth
像玻璃一样填充满父容器,阻止掉Auth
组件冒泡的tap
事件。当点击的时候实际上会先触发Auth
组件的tap
事件,父容器的tap
事件并不会触发。在Auth
组件中完成授权后,再抛出自定义的tap
事件,父容器的tap
事件触发,actAction
函数调用成功!非常完美
于是在我飞快的手速下,核心的代码也逐渐清晰了起来,键盘似乎也有了点儿糊味,哦!原来是 Tom 烧焦了~
Auth 组件的核心代码如下:
模版:
<-- catchtap 特别重要,这样可以捕获到点击,并且阻止冒泡给外层 -->
<view class="layer" catchtap="authCheckHandler" style="z-index:{{zIndex}};"></view>
样式表:
.layer {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
JS 部分:
Component({
properties: {
zIndex: {
type: Number,
value: 10
}
},
methods: {
authCheckHandler() {
const app = getApp();
app.authed().then(() => {
this.successHandler();
});
},
successHandler() {
// 触发 tap 事件
this.triggerEvent('tap', {}, {
bubbles: true, // @IMPORTANT 这个地方重要的配置,允许自定义事件冒泡
});
},
closeHandler() {
// 关闭授权弹窗
this.setData({
visible: false,
});
}
},
});
详细的代码我放在 wx-auth-demo 这个项目中,感兴趣的同学可以下载体验一下。核心的点就是通过 dom 嵌套 + 事件冒泡
,来替换 js
逻辑中的嵌套,接下来我还是要给自己鼓会儿掌~