微信小程序的登录和web端的登录有一点是不同的,小程序需要和微信的服务通信验证。
    
    
    1.小程序登录流程官网图
   
     
   
    
     2.认识
     
      openid
     
     ,
     
      unionid
     
     和
     
      code
     
    
    
    
     openid
    
   
    
     openid
    
    是用来唯一标识用户的一个字符串。在微信小程序中,每个用户的
    
     openid
    
    都是唯一的。通过
    
     openid
    
    ,小程序可以获取用户的基本信息,如头像、昵称等。
   
    注意:同一个用户在不同的小程序中拥有不同的
    
     openid
    
    。因此,在开发小程序时,不能使用
    
     openid
    
    来进行用户的唯一性判断。
   
    
     unionid
    
   
    
     unionid
    
    是在用户绑定同一微信开放平台账号下的多个应用时,用来唯一标识用户的一个字符串。如果用户在多个小程序中使用同一个微信号进行登录授权,那么这些小程序中的
    
     unionid
    
    都是相同的。
   
    注意:用户的
    
     unionid
    
    只有在用户将多个应用绑定到同一个微信开放平台账号下时才会生成。因此,如果用户没有绑定多个应用,那么小程序将无法获取用户的
    
     unionid
    
    。
   
    
     code
    
   
    
     code
    
    是用户登录凭证,由微信服务器颁发给小程序。在用户授权登录后,小程序可以通过调用微信登录接口获取用户的
    
     code
    
    。然后,通过
    
     code
    
    向微信服务器请求用户的
    
     openid
    
    和
    
     session_key
    
    等信息。
   
    注意:每个
    
     code
    
    只能使用一次,且有效期为5分钟。因此,在使用
    
     code
    
    进行登录时,需要及时将其转换成用户的openid和
    
     session_key
    
    等信息,以免出现
    
     code
    
    过期的情况
   
    
     openid
    
    、
    
     unionid
    
    和
    
     code
    
    是微信小程序登录授权中非常重要的三个参数,了解这些参数的作用和用法,有助于开发者更好地设计和开发小程序登录授权功能。
    
    3.文字版登录流程(面试会问这个,回答这个即可)
    
    通过
    
     wx.login()
    
    获取
    
     code
    
    。
   
    将这个
    
     code
    
    发送给后端,后端会返回一个
    
     token
    
    ,这个
    
     token
    
    将作为你身份的唯一标识。
   
    将
    
     token
    
    通过
    
     wx.setStorageSync()
    
    保存在本地存储。
   
    用户下次进入⻚面时,会先通过
    
     wx.getStorageSync()
    
    方法判断
    
     token
    
    是否有值,如果有值,则可以请求其它数据,如果没有值,则进行登录操作。
   
    4.图形流程(前端流程和后端流程)
    
    前端步骤:
   
    
     
   
    
     后端步骤:
    
   
     
   
    5. 代码实现登录流程
   
- 
简单的实现登录流程。 
   2. 再进一步完善:把登录封装成一个函数,然后判读本地是否有token有就不用执行登录函数,否则执行登录函数。 onLoad() { //获取token, 判断token是否有值 const token = wx.getStorageSync('token') || '' //如果有值 if(token) { console.log('请求其他数据'); }else{ this.handlerLogin() } }, //登录的回调函数 handlerLogin(){ wx.login({ success: res => { //获取code const code = res.code console.log(res); //将code发给后端请求token wx.request({ url: 'http://xxxxxxx/login', data:{ code }, method:'post', success:(res) =>{ const token = res.data.token //将token保存本地 wx.setStorageSync('token', token) console.log(res); } }) } }) },
- 
在一次优化代码: 
- 
看看刚刚写的代码的问题 
- 
  所以要对代码优化,把上面的代码进行拆分。 
- 
首先在项目的service文件夹下声明一个login.js用来获取code。使用promise返回成功的code 
   export const getCode = () => { new Promise((resolve, reject) => { wx.login({ success: res => { //获取code resolve(res.code) } }) }) }
- 
二次封装一个Promise版的request请求方法,在service下建立一个index.js(后面出一篇封装请求的文章) 
- 
  // 封装成类 class Request { constructor(baseURL) { this.baseURL = baseURL } request(options) { const { url } = options return new Promise((resolve, reject) => { wx.request({ ...options, url: this.baseURL + url, success: (res) => { resolve(res.data) }, fail: (err) => { console.log("err:", err); } }) }) } get(options) { return this.request({ ...options, method: "get" }) } post(options) { return this.request({ ...options, method: "post" }) } } export const loginRequest = new Request("http://xxxxxxx")
- 
使用自己封装的请求方法 
   import { loginRequest } from "./service/index"; import { getCode } from "./service/login"; // app.js App({ onLaunch() { const token = wx.getStorageSync('token') || '' // 登录 if(token) { console.log('请求其他数据'); }else{ this.handlerLogin() } }, //登录的回调函数 async handlerLogin(){ //获取code const code = await getCode() //将code发给后端请求token const res = await loginRequest.post({ url:"/login", data:{code} }) //保存token wx.setStorageSync('token', res.token) }, }
- 
对比优化前后 
   
- 
添加一个判断token是否过期,本地的token可能有可能没有,有的token的话,token还有可能是否过期,token是有时效的。后端给我们一个借口验证token是否过期的。 
   最后:发一个总体代码:结合实际更改代码 import { loginRequest } from "./service/index" import { getCode } from "./service/login" // app.js App({ async onLaunch() { //获取本地token const token = wx.getStorageSync('token') || '' //检查token是否过期 const res = await loginRequest.post({ url: '/auth', header: { token } }) console.log(res); // 登录 if (token && res.message === "已登录") { console.log('请求其他数据'); } else { this.handlerLogin() } }, //登录的回调函数 async handlerLogin() { //获取code const code = await getCode() //将code发给后端请求token const res = await loginRequest.post({ url: "/login", data: { code } }) //保存token wx.setStorageSync('token', res.token) }, }) //service/index.js代码 // 封装成类 class Request { constructor(baseURL) { this.baseURL = baseURL } request(options) { const { url } = options return new Promise((resolve, reject) => { wx.request({ ...options, url: this.baseURL + url, success: (res) => { resolve(res.data) }, fail: (err) => { console.log("err:", err); } }) }) } get(options) { return this.request({ ...options, method: "get" }) } post(options) { return this.request({ ...options, method: "post" }) } } export const loginRequest = new Request("http://xxxxx") //service/login.js export const getCode = () => { new Promise((resolve, reject) => { wx.login({ success: res => { //获取code resolve(res.code) } }) }) }
 
