跳至主要內容

API

chanchaw大约 8 分钟mini

概述

官方提供的 api 不允许小程序的前端页面中直接调用,开发者应该是调用自己的后台,在后台中使用微信官方提供的 api ,见 [官方API介绍](基础 | 微信开放文档open in new window)

微信用户信息

登录

在页面加载的生命周期函数 onLoad 中可以立即调用 wx.login() 获取 code ,从而为后面获取用户信息做好准备,响应来的 code 只有5分钟的有效期,并且只能使用一次。详细介绍参见官方文档open in new window

onLoad() {
    console.log('进入index页面的onLoad');
    wx.login({
      success(res){
        console.log('onLoad中用户登录请求得到的响应是:', res);
        if(!res) return;
        const code = res.code || '';
      },
      fail(err){
        console.log('onLoad中用户登录请求失败:', );
      }
    })
},

success 拿到的响应结果的模型是

{"errMsg":"login:ok","code":"sdfadsfasdfasdf"}

官方要求开发者通过 wx.login() 获得 code 后应请求开发者自己的后台服务并调用 code2Session 获取用户的 openId 和 unionId。如果多次调用 wx.login() 都没有请求 code2Session 会进入 wx.login()fail 分支,并相应下面的报错信息:

errMsg:login:fail INVALID_LOGIN,access_token expired [20241121 12:59:30][wxf23fe29ef6ac21a7]

初次制作微信小程序是访客系统,参见 后台项目open in new window 的API /wxmp/getUserProfile

unionId

官方关于 unionId 的 [UnionID机制说明](UnionID 机制说明 | 微信开放文档open in new window)

在制作访 客系统 时在 自定义工具jaropen in new window 中新增了实体类 com.cc.alltype.wechat.MiniGetUserProfileRes 用于接收请求用户 openIdunionId 的响应结果。

获取用户 openId

2024年9月21日 16:08:19 查看官网文档,现使用 wx.getUserProfile 替换之前的 wx.getUserInfo ,该接口不可在 onLoad 之类的自动执行的生命周期函数中获取用户信息,微信官方要求在用户出现点击动作时才可以获取,例如点击某个按钮的事件中。否则返回的响应是 {errMsg:"getUserProfile:fail can only be invoked by user TAP gesture."} 。要先通过 wx.login() 获取当前用户的 code ,使用该 code 通过请求开发者自己的后台服务获取微信用户 openId - 开发者后台服务中请求微信 API 获取 openId,初次实现在仓库 visitoropen in new window 的方法 app.ts # getUserInfo 中。

手机号验证

分为两种:手机号快速验证组件、手机号实时验证组件。前者是获取微信用户的手机号 <button open-type="getPhoneNumber" bind:getphonenumber="getphonenumber" />

后者是每次请求时平台均会对用户选择的手机号进行验证 <button open-type="getRealtimePhoneNumber" bind:getrealtimephonenumber="getrealtimephonenumber">

注意:该获取手机号的接口针对非个人开发者,其完成了认证的小程序开放(不包含海外主体),两种验证组件需要付费使用,每个小程序账号将有1000次的体验额度。

分享到朋友圈

开启该功能要求:

  1. 页面允许 “发送给朋友”,即 js 页面声明函数 onShareAppMessage
  2. 页面必须声明 onShareTimeline 函数
Page({
  onShareTimeline(){
    return {
      title: '帮我砍一刀~~~~',
      query: 'id=11',
      imageUrl: '/assets/floor/1.jpg'
    }
  },
})

转发功能

转发个人/群

参见 官方文档转发 | 微信开放文档open in new window

要实现转发小程序给微信好友或者给微信群需要用到微信API [onShareAppMessage](Page(Object object) | 微信开放文档open in new window)

分享到朋友圈

需要调用微信API [onShareTimeline](Page(Object object) | 微信开放文档open in new window)

有两种方法可以实现转发功能

  1. 页面 js 文件必须声明 onShareAppMessage 事件监听器,并自定义转发内容。只有定义了此事件处理函数右上角菜单才会显示转发按钮
  2. 通过给 button 组件设置属性 open-type='share' 可以在用户点击按钮后触发 Page.onShareAppMessage 事件监听函数

设置下面代码后通过右上角三个点打开的菜单第一项就是分享功能

Page({
  onShareAppMessage(){
    return{
      title: '这是个神奇的地方',
      path: '/pages/cate/cate',
      imageUrl: '/assets/floor/1.jpg'
    }
  },
}

获取微信昵称

通过下面三步获取

  1. 通过 form 组件中包裹 input 以及 form-type = submit 的 button 组件
  2. 需要将 input 组件 type 设置为 nickname ,当用户输入框输入时,键盘上方会展示微信昵称
  3. 给 form 绑定 submit 事件,在事件处理函数中通过事件对象获取用户昵称

注意要先点击 form 中的 input 在屏幕最下面会出现当前微信账号的昵称,选择后点击按钮,后台通过表单的提交函数获取用户昵称

<form bindsubmit="onSubmit">
  <input type="nickname" name="nickname" placeholder="请输入昵称"/>
  <button type="primary" plain form-type="submit">点击获取昵称</button>
</form>

onSubmit(event){
    console.log(event)
    console.log(event.detail.value.nickname)
}

获取头像

在按钮上使用属性 open-type="chooseAvatar" 并绑定事件 bind:chooseavatar ,后者绑定的函数代码如下,其中得到的 url 即是用户的微信头像

  chooseAvatar(event){
    console.log(event)
    const url = event.detail.avatarUrl
    if(url){
      this.setData({
        avatarUrl: url
      })
    }
  }

注意此方法获取的头像地址是临时的,还要将头像图片上传到自己的服务器上再使用。此处获取微信头像的完整代码如下

<view>
  <button class="btn" open-type="chooseAvatar" bind:chooseavatar="chooseAvatar">
    <image class="avatar" src="{{ avatarUrl }}"/>
  </button>
</view>

Page({
  data:{
    avatarUrl: '/assets/floor/1.jpg',
  },

  chooseAvatar(event){
    console.log(event)
    const url = event.detail.avatarUrl
    if(url){
      this.setData({
        avatarUrl: url
      })
    }
  }
})

本地存储

不同于 html 的是,小程序中本地存储不需要使用 JSON.stringify()JSON.parse() 来兼容对象和基本类型的变量

异步CRUD:wx.setStorage()wx.getStorage()wx.removeStorage()wx.clearStorage()

同步CRUD:wx.setStorageSync()wx.getStorageSync()wx.removeStorageSync()wx.clearStorageSync()

下面演示同步方式的本地存储

wx.setStorageSync('num', 11)
wx.setStorageSync('obj', {id: 1001, name: '张三'})
const num = wx.getStorageSync('num')
const obj = wx.getStorageSync('obj')
console.log(num,obj)

下面演示异步本地存储的使用方法

async handleStorage(){
    wx.setStorage({
      key: 'num',
      data: 12
    })
    wx.setStorage({
      key: 'obj',
      data: {
        id: 1002,
        name: '李四'
      }
    })

    const num = await wx.getStorage({key:'num'})
    const obj = await wx.getStorage({key:'obj'})
    console.log(num,obj)
  },

异步API

概述

通常接受一个 object 类型的参数,例如:wx.request({})。当借口参数 Object 对象中不包含 success/fail/complete 时将默认返回 Promis,部分接口如 request,uploadFile 本身就有返回值,因此不支持 Promise 风格的调用方式,他们的 promisify 需要开发者自行封装。

网络请求

使用 wx.request() 发起网络请求,要求相关域名必须在微信公众平台进行配置,否则会在控制台报错。

封装Promise对象

下面代码封装微信官方提供的API wx.login() 方法,返回一个 Promise 对象,调用方法 wxLogin$().then(res => {...},err => {...}),前面是成功的回调,后面是失败的回调。

// 下面是 http.ts 文件的代码
const wxLogin$ = (): Promise<string> => {
  return new Promise((resolve, reject) => {
    wx.login({
      success: res => {
        if(res.code) {
          resolve(res.code)// 返回微信服务器响应来的 code(用于请求openId等用户信息)
        }else {
          console.log('执行微信登录函数wx.login时出现异常!- http.ts#wxLogin$.success');
          console.log(res);
        }
      },
      fail: err => {// 登录失败写入后台日志表log_error
        console.log('执行微信登录函数wx.login时出现异常!- http.ts#wxLogin$');
        console.log(err);
        reject(err);
      }
    })
  })
}
export { wxLogin$ }

同步API

约定以 Sync 结尾,例如:wx.setStorageSync()

事件监听API

约定以on开头,例如:wx.onAppHide()

上拉加载

  1. 设置触底的高度

    {
      "usingComponents": {},
      "onReachBottomDistance": 100
    }
    
  2. 页面添加多个 view 用于显示

    <!--pages/market/market.wxml-->
    <text>pages/market/market.wxml</text>
    <view class="line"></view>
    <block wx:for="{{numList}}" wx:key="index">
    <view>{{item}}</view>
    </block>
    
  3. 为 view 制作显示样式,可以下拉越界

    /* pages/market/market.wxss */
    view {
      height: 400rpx;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    view:nth-child(odd){
      background-color: lightskyblue;
    }
    view:nth-child(even){
      background-color: lightsalmon;
    }
    
  4. js控制触底后的逻辑。下面代码中使用 setTimeout 模拟获取异步数据需要耗时,能清楚的看到加载动画

    // pages/market/market.ts
    Page({
      data: {
        numList: [1,2,3]
      },
    
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom() {
        wx.showLoading({title:'数据加载中...'})
    
        setTimeout(() => {
          const lastEle = this.data.numList[this.data.numList.length-1]
          console.log('默认数据数组最后一个元素是:' + lastEle)
          let newArr = []
          for(let i=0;i<3;i++){
            const newEle = lastEle + i + 1
            console.log('最新的元素:' + newEle)
            newArr.push(newEle)
          }
          console.log('新增的数组:', newArr)
          this.setData({
            numList:[...this.data.numList,...newArr]
          })
          console.log(this.data.numList)
    
          wx.hideLoading()
        }, 1500);
      },
    })
    

下拉刷新

// 在页面 json 文件中做如下配置
{
  "usingComponents": {},
  "enablePullDownRefresh": true,// 开启下拉刷新功能,页面的配置会覆盖 app.json 中的设置
  "backgroundColor": "#efefef",
  "backgroundTextStyle": "light"
}

// js 文件中制作触发事件后的逻辑
  onPullDownRefresh(){
    console.log('....');
    // 可能会出现下拉刷新的窗口不退出,要手动退出
    if(this.data.numList.length === 3) wx.stopPullDownRefresh()
  },

scroll-view上拉、下拉功能

<!-- wxml 代码 -->
<scroll-view 
  scroll-y 
  class="scroll-y"

  lower-threshold="100"
  bind:scrolltolower="getMore"
  enable-back-to-top="true"

  refresher-enabled
  refresher-default-style="black"
  refresher-background="#f7f7f8"
  bind:refresherrefresh="handlPulldownRefresh"
  refresher-triggered="{{expand}}"
>
<!-- wx:key的*this表示数组元素本身 -->
<view wx:for="{{numList}}" wx:key="*this">
  {{item}}
</view>
</scroll-view>

<!-- scss 代码 -->
.scroll-y {
  height: 100vh;
  background-color: #efefef;
}
view {
  height: 500rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}

view:nth-child(odd){
  background-color: lightblue;
}

view:nth-child(even){
  background-color: lightsalmon;
}

<!-- js代码 -->
Page({
  data:{
    numList: [1,2,3],
    expand: false
  },
  handlPulldownRefresh(){
    this.setData({
      numList: [1,2,3],
      expand: false
    })
  },
  getMore(){
    wx.showLoading({title:'数据加载中...'})

    setTimeout(() => {
      const lastEle = this.data.numList[this.data.numList.length-1]
      console.log('默认数据数组最后一个元素是:' + lastEle)
      let newArr = []
      for(let i=0;i<3;i++){
        const newEle = lastEle + i + 1
        console.log('最新的元素:' + newEle)
        newArr.push(newEle)
      }
      console.log('新增的数组:', newArr)
      this.setData({
        numList:[...this.data.numList,...newArr]
      })
      console.log(this.data.numList)

      wx.hideLoading()
    }, 1500);
  },
})