小程序系统Api的调用(登录流程详解)

1,694 阅读5分钟

1. 网络请求API

微信提供了专属的API接口,用于网络请求: wx.request(Object object)

image.png

  • 基本使用

    wx.request({
      url: 'http://codercba.com:1888/api/home/houselist',
      data: {
        page: 1
      },
      success: (res) => {
        const data = res.data.data
        this.setData({ houselist: data })
      },
      fail: (err) => {
        console.log("err:", err);
      }
    })
    
  • 域名配置

    • 每个微信小程序需要事先设置通讯域名,小程序只可以跟指定的域名进行网络通信。

      • 小程序登录后台 – 开发管理 – 开发设置 – 服务器域名;
    • 服务器域名请在 「小程序后台 - 开发 - 开发设置 - 服务器域名」 中进行配置,配置时需要注意:

      • 域名只支持 https (wx.request、wx.uploadFile、wx.downloadFile) 和 wss (wx.connectSocket) 协议

      • 域名不能使用 IP 地址(小程序的局域网 IP 除外)或 localhost

      • 可以配置端口,如 https://myserver.com:8080,但是配置后只能向 https://myserver.com:8080 发起请求。如果向https://myserver.comhttps://myserver.com:9091 等 URL 请求则会失败

      • 如果不配置端口。如 https://myserver.com,那么请求的 URL 中也不能包含端口,甚至是默认的 443 端口也不可以。如果向 https://myserver.com:443 请求则会失败

      • 域名必须经过 ICP 备案

      • 出于安全考虑,api.weixin.qq.com 不能被配置为服务器域名,相关 API 也不能在小程序内调用。 开发者应将 AppSecret 保存到后台服务器中,通过服务器使用 getAccessToken 接口获取 access_token,并调用相关 API

      • 不支持配置父域名,使用子域名。

  • 工具封装:

    • 函数封装

      function ysRequest(options) {
        return new Promise((resolve, reject) => {
          wx.request({ 
            ...options, 
            success: (res) => {
              resolve(res.data)
            },
            fail: reject
          })
        })
      }
      
    • 类封装

      class YSRequest {
        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 ysReqInstance = new YSRequest("http://codercba.com:1888/api")
      

2. 弹窗和分享

  • 小程序中展示弹窗有四种方式: showToast、showModal、showLoading、showActionSheet
  • showToast

  • showModal

  • showActionSheet

    <view>
      <button size="mini" bindtap="onShowToast">showToast</button>
      <button size="mini" bindtap="onShowModal">showModal</button>
      <button size="mini" bindtap="onShowAction">showAction</button>
    </view>
    
    onShowToast() {
      wx.showToast({
        title: '购买失败!',
        icon: "error",
        duration: 5000,
        mask: true,
        success: (res) => {
          console.log("res:", res);
        },
        fail: (err) => {
          console.log("err:", err);
        }
      })
    
      // wx.showLoading({
      //   title: "加载中ing"
      // })
    },
    onShowModal() {
      wx.showModal({
        title: "确定购买吗?",
        content: "确定购买的话, 请确定您的微信有钱!",
        confirmColor: "#f00",
        cancelColor: "#0f0",
        success: (res) => {
          if (res.cancel) {
            console.log("用户点击取消");
          } else if (res.confirm) {
            console.log("用户点击了确定");
          }
        }
      })
    },
    onShowAction() {
      wx.showActionSheet({
        itemList: ["衣服", "裤子", "鞋子"],
        success: (res) => {
          console.log(res.tapIndex);
        },
        fail: (err) => {
          console.log("err:", err);
        }
      })
    },
    
  • onShareAppMessage

    • 分享是小程序扩散的一种重要方式,小程序中有两种分享方式:

      • 方式一:点击右上角的菜单按钮,之后点击转发

      • 方式二:点击某一个按钮,直接转发

    • 当转发给好友一个小程序时,通常小程序中会显示一些信息(通过 onShareAppMessage)

      • 监听用户点击页面内转发按钮(button 组件 open-type="share")或右上角菜单“转发”按钮的行为,并自定义转发内容。
      • 此事件处理函数需要 return 一个 Object,用于自定义转发内容
    onShareAppMessage() {
      return {
        title: "测试的内容",
        path: "/pages/favor/favor",
        imageUrl: "/assets/nhlt.jpg"
      }
    },
    

3. 设备和位置信息

  • 在开发中,需要经常获取当前设备的信息,用于收集手机信息或者进行一些适配工作。
    • 小程序提供了相关个API:wx.getSystemInfo(Object object)
  • wx.getSystemInfo():获取当前设备的信息

  • wx.getLocation():获取当前的位置信息

    • app.json配置
    "permission": {
      "scope.userLocation": {
        "desc": "需要获取您的位置信息"
      }
    },
    
    • 使用
    onGetSystemInfo() {
       // 1.获取手机的基本信息
       wx.getSystemInfo({
         success: (res) => {
           console.log(res);
         }
       })
    
       // 2.获取当前的位置信息
       wx.getLocation({
         success: (res) => {
           console.log("res:", res);
         }
       })
     },
    

4. Storage的存储

  • 同步存取数据的方法:

    • wx.setStorageSync(string key, any data)
    • wx.getStorageSync(string key)
    • wx.removeStorageSync(string key)
    • wx.clearStorageSync()
  • 异步存储数据的方法:

    • wx.setStorage(Object object)
    • wx.getStorage(Object object)
    • wx.removeStorage(Object object)
    • wx.clearStorage(Object object)
    // 异步操作
    wx.setStorage({
      key: "books",
      data: "哈哈哈",
      // 是否加密存储
      encrypt: true, // 需要在2.21版本中使用
      success: (res) => {
        wx.getStorage({
          key: "books",
          encrypt: true,
          success: (res) => {
            console.log(res);
          }
        })
      }
    })
    

5. 页面跳转和数据传递

5.1 页面跳转

image.png

  • navigateTo

    Page({
      data: {
        name: "kobe",
        age: 30,
        message: "哈哈哈"
      },
      onNavTap() {
        const name = this.data.name
        const age = this.data.age
    
        // 页面导航操作
        wx.navigateTo({
          // 跳转的过程, 传递一些参数过去
          url: `/pages2/detail/detail?name=${name}&age=${age}`,
          events: {
            backEvent(data) {
              console.log("back:", data);
            },
            test(data) {
              console.log("test:", data);
            }
          }
        })
      }
    })
    
  • navigateBack

    // 在 C 页面内 navigateBack,将返回 A 页面
    wx.navigateBack({
      delta: 2
    })
    

5.2 数据传递:

image.png

  • ?queryString

  • getCurrentPages -> prePage.setData

    • 返回时传递数据的场景(填写表单后返回)
    // 在页面卸载的时候
    onUnload() {
    // 2.1. 获取到上一个页面的实例
    const pages = getCurrentPages()
    const prePage = pages[pages.length-2]
    
    // 2.2.通过setData给上一个页面设置数据
      prePage.setData({ message: "呵呵呵" })
    }
    
    // 2.方式一: 给上一级的页面传递数据
    // 2.1. 获取到上一个页面的实例
    const pages = getCurrentPages()
    const prePage = pages[pages.length-2]
    
    // 2.2.通过setData给上一个页面设置数据
    prePage.setData({ message: "呵呵呵" })  
    
  • events -> eventChannel

    // 3.1. 拿到eventChannel
    const eventChannel = this.getOpenerEventChannel()
    
    // 3.2. 通过eventChannel回调函数
    eventChannel.emit("backEvent", { name: "back", age: 111 })
    eventChannel.emit("test", { name: "test", age: 10 })
    

5.3 组件跳转

  • navigator组件

    <navigator class="nav" url="/pages2/detail/detail?name=kobe&age=18">跳转</navigator>
    <navigator open-type="navigateBack">返回</navigator>
    

6. 登录流程

  • 如何识别同一个小程序用户身份?

    • openid和unionid
      • openid: 用户用微信静默登录当前小程序生成,标识用户身份的唯一标识
      • unionid: 不同产品之间标识同一用户身份(如小程序和公众号)
    • 获取code
    • 换取authToken
  • 用户身份多平台共享

    openid 和 手机号/用户名进行绑定

    • 账号绑定
    • 手机号绑定
  • 登录流程 image.png

  • 代码演练

    wx.login({
      success: (res) => {
        const code = res.code
    
        // 2.将这个code发送自己的服务器(后端)
        wx.request({
          url: "http://123.207.32.32:3000/login",
          data: {
            code
          },
          method: "post",
          success: (res) => {
            const token = res.data.token
            wx.setStorageSync('token', token)
          }
        })
      }
    })
    
    export function getCode() {
      return new Promise((resolve, reject) => {
        wx.login({
          success: (res) => {
            resolve(res.code)
          }
        })
      })
    }
    
    export const loginReqInstance = new YSRequest("http://123.207.32.32:3000")
    
    async onLaunch() {
      // 1.获取token, 判断token是否有值
      const token = wx.getStorageSync('token') || ""
    
      // 2.判断token是否过期
      const res = await loginReqInstance.post({
        url: "/auth",
        header: {
          token: token
        }
      })
    
      // 2.如果token有值
      if (token && res.message === "已登录") {
        console.log("请求其他的数据");
      } else {
        this.handleLogin()
      }
    },
    async handleLogin() {
      // 1.获取code
      const code = await getCode()
    
      // 2.使用code换取token
      const res = await loginReqInstance.post({
        url: "/login",
        data: { code }
      })
    
      // 3.保存token
      wx.setStorageSync('token', res.token)
    }