共计 5898 个字符,预计需要花费 15 分钟才能阅读完成。
在理解小程序登录之前,请大家先理解小程序的全局实例和全局组件,以不便了解本文的后续内容,曾经理解的能够间接开始。
全局实例和全局组件(👈 点击中转)
微信小程序的登录流程
微信小程序的登录
首先须要写一个微信小程序的登录弹窗,登录弹窗的作用就是发动登录,让用户点击受权后登录小程序,该弹窗是一个全局弹窗,因为小程序是有分享性能的,如果新用户是从分享的链接进来的,那么会先让新用户登录再做后续操作。
所以,登录性能得是一个组件,而且,登录必须是全局弹窗。
在登录页面的 index.json
文件中,设置登录弹窗为组件
{
"component": true,
"usingComponents": {// xxxx.....}
}
登录弹窗上须要有受权的选项,如果未勾选受权间接点击登录,须要提醒用户先受权再登录
用户勾选受权后,点击登录。小程序登录须要应用 button
组件,将 button
组件的 open-type
的值设置为 getPhoneNumber
,当用户点击并批准之后,能够通过 bindgetphonenumber
事件回调获取到动静令牌 code
,而后把code
传到开发者后盾,并在开发者后盾调用微信后盾提供的 phonenumber.getPhoneNumber
接口,生产 code
来换取用户手机号。并且每个 code
有效期为 5
分钟,且只能生产一次。
open-type=”getPhoneNumber” 应用文档(👈 点击中转)
注:
getPhoneNumber
返回的code
与wx.login
返回的code
作用是不一样的,不能混用。
<button open-type="getPhoneNumber" bindgetphonenumber="handleConfirm"></button>
data: {
show: false, // 登录弹窗是否显示
selected: true, // 是否勾选受权
loginSuccess: undefined,
loginFail: undefined,
},
// 确认受权手机号 - 这里能够做节流操作,避免用户点击次数过多,为了便于演示,这里未做节流
async handleConfirm(data) {const {selected} = this.data
// 用户未勾选,提醒请勾选
if(!selected){
wx.showToast({
title: '请批准《用户隐衷协定》',
icon: 'none'
})
return
}
// data.detail.code 就是获取手机号的动静令牌
let info = data.detail
let fail = this.data.loginFail
if (info.code) {
// info.code 就是手机号动静令牌
/** 新版本微信小程序不须要提前调用 wx.login 进行登录,这里的写法是为了实配老版本,在获取手机号受权登录之前先调用 wx.login
这里的 app.globalData.userInfo 为全局挂载的 userInfo,对于 userInfo 的解释在本文下方
*/
/* 应用 awiat 阻塞过程 */
await app.globalData.userInfo._getLoginCode() // wx.login 登录
// 调用了 wx.login 后进入下一步
this.setPhoneInfo(info) // 绑定手机号 - 获取手机号受权用户登录性能
} else {fail && fail(info)
}
},
// 绑定手机号 - 获取手机号受权用户登录性能
setPhoneInfo(data) {
let success = this.data.loginSuccess
let fail = this.data.loginFail
// data.jsCode 保留通过 login 获取的 code
data.jsCode = app.globalData.userInfo.code
// 手机号动静令牌
data.phoneCode = data.code
// 调用用户登录接口,removeNull 其实是一个封装的办法,用来去掉空格,实质就是传了一个 data
getLoginSession(removeNull(data)).then(async res => {
// then 为登录胜利,存入 token
wx.setStorageSync('token', res.data)
// 手机号受权算登录胜利
success && success()
// 设置全局 userInfo 属性,isLogin = true,示意登录胜利
app.globalData.userInfo.isLogin = true
// 革除期待列表
wx.queue.asyncExe("login_back")
// 调用全局的_getUserInfo 办法, 传入 'login' 参数
await app.globalData.userInfo._getUserInfo('login')
// 敞开弹框
this.hideLogin()}).catch(async e => {if (e.data.indexOf("已绑定") > -1) {success && success()
wx.setStorageSync("token", e.data)
await app.globalData.userInfo._getUserInfo('login')
} else {fail && fail()
}
// 敞开弹框
this.hideLogin()})
},
// 敞开弹框
hideLogin() {
// 敞开弹框
this.setData({show: false}, () => {if (isPopup()) {// 显示 tabbar()
setTimeout(() => {this.getTabBar().show()}, 300)
}
})
},
旧版本的微信小程序是须要提前调用 wx.login
获取 code
能力进行下一步操作,而新版本则不须要提前调用 wx.login
进行登录。
wx.login 文档(👈 点击中转)
上面是 userInfo.js
文件,该文件外部创立了一个 class
类,该类会挂载到全局实例身上
// userInfo.js
import {getUserInfo} from '../service/user'
class UserInfo {
code = '' // 用户受权登录时须要用到的 code
isLogin = false // 判断用户是否曾经登录拿到 token
isInfo = false // 判断用户是否曾经登录了
/**
* 获取用户信息
*/
_getUserInfo(type) {return new Promise((resolve,reject)=>{
// isInfo 初始化为 false,示意未登录过,如登录过 isInfo = true, 如果登录过则间接获取本地的 token
if(type=="login"&&this.isInfo) return resolve(wx.getStorageSync('userInfo'))
this.isInfo = true
// 调用获取用户信息的接口
getUserInfo().then(res=>{
// 如果返回 200,拿到 token 当前,保留用户的信息,次要是名称和头像
if (res.code == 200) {
// 保留用户信息到本地
wx.setStorageSync('userInfo', res.data)
// resolve 返回
resolve(res)
}
// 不等于 200 isInfo = false,示意曾经登录过,从新获取即可
this.isInfo = false
// 不等于 200 返回错误信息
reject(res)
},(err)=>{
// 不等于 200 isInfo = false,示意曾经登录过,从新获取即可
this.isInfo = false
// 不等于 200 返回错误信息
reject(err)
})
})
}
/**
* 通过 wx.login 获取 code
* 不全局调用,每次受权调用 Login 办法前,都从新获取一次
*/
async _getLoginCode() {
try {const loginCodeRes = await wx.p.login()
console.log(loginCodeRes)
/**loginCodeRes.code : 用户登录凭证(有效期五分钟)。开发者须要在开发者服务器后盾调用 code2Session,应用 code 换取 openid、unionid、session_key 等信息 */
// 将该 code 挂载到全局的 global.userInfo 中
this.code = loginCodeRes.code
} catch (error) {console.error(error, 'get jscode error');
}
}
}
export default UserInfo
// app.js
import UserInfo from './private/UserInfo'
App({
/** 小程序生命周期,全局调用一次 onLaunch */
onLaunch(e) {/**new UserInfo() */
this.globalData.userInfo = new UserInfo()},
onShow(e) {},
globalData: {
userInfo: null, /**private -> UserInfo 的属性和办法挂载到这里 */
show:false
}
})
流程总结
通过 getPhoneNumber
的形式登录
1、components
中创立 auth
文件夹,该文件夹就是内的 html
就是小程序的登录弹窗,auth
是一个全局组件,在 app.json
中挂载
2、在 private
文件夹中封装小程序的登录办法 ——> UserInfo.js
——> js
文件内创立 class
类,在 class
中封装办法并导出
3、在 app.js
的onLaunch
中 new UserInfo
获取之前封装好的小程序登录办法,该办法挂载到globalData.userInfo
中
import UserInfo from './private/UserInfo'
App({onLaunch(e){this.globalData.userInfo = new UserInfo()
}
})
4、auth
文件夹为小程序的全局受权登录弹窗,从根底库 2.21.2
开始,对获取手机号的接口进行了平安降级,新版小程序须要用户主动触发能力获取手机号接口,需用 button 组件的点击来触发。新版小程序不再须要提前调用 wx.login
进行登录
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
Page({getPhoneNumber (e) {console.log(e.detail.code) // 该 code 就是动静令牌,用于换取用户手机号
}
})
须要将 button 组件 open-type
的值设置为 getPhoneNumber
,当用户点击并批准之后,能够通过 bindgetphonenumber
事件回调获取到动静令牌 code
,而后把code
传到开发者后盾,并在开发者后盾调用微信后盾提供的 phonenumber.getPhoneNumber 接口,生产 code
来换取用户手机号。每个 code
有效期为 5 分钟,且只能生产一次。
注:
getPhoneNumber
返回的code
与wx.login
返回的code
作用是不一样的,不能混用。
5、用户点击弹框后,先让用户勾选协定,勾选后才容许点击登录,调用登录接口,将登录接口独自封装起来,将获取到的 code
手机号动静令牌当参数传入登录办法。
新版本微信不许要提前调用
login
来获取code
码,旧版本微信小程序是须要提前调用login
获取code
码为了演示,所以这里提前调用
wx.login
来获取code
码,并将该code
码存入全局app.globalData.userInfo
中,须要留神的是,该code
码的有效期是5 分钟
6、调用登录办法,携带 code
手机号动静令牌和接口规定的必传参数,申请登录接口,返回 200
为登录胜利,
1)、将登录胜利的 token 存入本地
2)、设置全局属性 app.globalData.userInfo.isLogin = true 示意登录胜利
3)、革除期待列表
7、调用获取用户信息接口,也就是全局挂载的await app.globalData.userInfo._getUserInfo()
,敞开登录弹框
await app.globalData.userInfo._getUserInfo('login')
8、获取用户信息接口,通过传入的参数判断是是否要登录,这里有两种状况:
1)、用户曾经登录了,只是想从新获取一下 token
2)、用户第一次登录,要获取用户信息,例如头像、用户名称
依据这两种状况,传入的参数 "login"
当然是不够的,所以须要再加一个状态,isInfo
,isInfo
默认为false
/**
* 获取用户信息
*/
_getUserInfo(type) {return new Promise((resolve,reject)=>{
// 用户登录过
if(type=="login"&&this.isInfo) return resolve(wx.getStorageSync('userInfo'))
// 设置 isInfo = true,因为上面要走获取用户信息流程,获取后,第二次调用_getUserInfo 判断 isInfo = true, 间接 return 掉
this.isInfo = true
// 调用获取用户信息的接口
getUserInfo().then(res=>{
// 如果返回 200,拿到 token 当前,保留用户的信息,次要是名称和头像
if (res.code == 200) {
// 保留用户信息到本地
wx.setStorageSync('userInfo', res.data)
// resolve 返回
resolve(res)
}
// 不等于 200 isInfo = false,示意曾经登录过,从新获取即可
this.isInfo = false
// 不等于 200 返回错误信息
reject(res)
},(err)=>{
// 不等于 200 isInfo = false,示意曾经登录过,从新获取即可
this.isInfo = false
// 不等于 200 返回错误信息
reject(err)
})
})
}
最初附上微信官网对登录的阐明(👈 点击中转)
以上就是微信小程序的登录流程,这些步骤都是按理论需要编写的,有些时候流程的 2、3、4、5、6 都是混着写的,大家能够依据我的项目的理论需要做自在调整。
如果感觉这篇文章对你有帮忙,欢送点赞、珍藏、转发哦~