当前位置: 首页 > 工具软件 > App.js > 使用案例 >

微信小程序学习:(二)app.js及index.js详解

鲜于海
2023-12-01

微信小程序学习:(二)app.js及index.js详解

项目地址:https://github.com/leoricding/-

在用ide创建小程序项目时,系统默认为我们创建了一个helloword的样例模板:包括查询用户设置、获取用户信息、返回用户名及头像、页面跳转等。下面我就一一解析:

1、app.js

这是小程序的入口,启动小程序时首先调用app.js。

App()注册小程序,然后内部按生命周期执行。

//app.js
//注册小程序
App({
  onLaunch: function () {
    console.log("app.js初始化")
      
    // 展示本地存储能力
    // 往本地存储写入log数据,登录日志
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)

    // 登录
    // 用户登录小程序
    wx.login({
      success: res => {
        // 登录成功后的回调
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
        console.log('wx.login登录成功')
      }
    })
      
	// 重点在这
    // 获取用户的设置,返回用户的授权信息
    // 判断用户是否授权,若已经授权,调用wx.getUserInfo接口获取用户信息,
    // 将获取的信息存到全局状态this.globalData.userInfo
    // 若用户未授权,直接逃过,进入index页面
    wx.getSetting({
      success: res => {

        // 获取成功的回调
        console.log('获取用户的当前设置,返回授权后的信息')
        console.log(res)

        //判断用户是否授权
        if (res.authSetting['scope.userInfo']) {
          // 已经授权,则无需重复授权
          // 可以直接调用 wx.getUserInfo 获取用户信息,不会弹框
          console.log("用户已经授权")
          wx.getUserInfo({
            success: res => {
              // 获取用户信息成功后的回调
              // 可以将 res 发送给后台解码出 unionId
              // 将用户信息赋值给this.globalData.userInfo
              this.globalData.userInfo = res.userInfo
              console.log('app.js中获取用户信息成功')
              console.log(this.globalData.userInfo)

              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
              // 所以此处加入 callback 以防止这种情况
              // app.userInfoReadyCallback是在index的onLoad函数中定义的
              // 判断userInfoReadyCallback这个属性是否存在
              // 如果存在,则执行,将用户数据赋值给globalData及index中的data
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    })
  },
  // 全局状态
  globalData: {
    userInfo: null
  }
})

(1)在onLoad函数中,首先将小程序的登录日志写入到本地。

每加载一次小程序,就写入一次。

	// 展示本地存储能力
    // 往本地存储写入log数据,登录日志
    var logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)

(2)小程序登录。

调用wx.login接口,换取 openId, sessionKey, unionId

有后端API才有用,这里没有后端,所以只打印了一下

	// 登录
    // 用户登录小程序
    wx.login({
      success: res => {
        // 登录成功后的回调
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
        console.log('wx.login登录成功')
      }
    })

(3)读取用户信息。

wx.getSetting()获取用户设置(返回用户的已授权信息)

若已授权(res.authSetting[‘scope.userInfo’]存在),通过wx.getUserInfo调用用户信息。调用成功后,写入全局状态this.globalData.userInfo,然后index页面中通过onLoad函数调用globalData.userInfo,在index页面显示用户信息。

	// 重点在这
    // 获取用户的设置,返回用户的已授权信息
    // 判断用户是否授权,若已经授权,调用wx.getUserInfo接口获取用户信息,
    // 将获取的信息存到全局状态this.globalData.userInfo
    // 若用户未授权,直接逃过,进入index页面
    wx.getSetting({
      success: res => {

        // 获取成功的回调
        console.log('获取用户的当前设置,返回授权后的信息')
        console.log(res)

        //判断用户是否授权
        if (res.authSetting['scope.userInfo']) {
          // 已经授权,则无需重复授权
          // 可以直接调用 wx.getUserInfo 获取用户信息,不会弹框
          console.log("用户已经授权")
          wx.getUserInfo({
            success: res => {
              // 获取用户信息成功后的回调
              // 可以将 res 发送给后台解码出 unionId
              // 将用户信息赋值给this.globalData.userInfo
              this.globalData.userInfo = res.userInfo
              console.log('app.js中获取用户信息成功')
              console.log(this.globalData.userInfo)

              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
              // 所以此处加入 callback 以防止这种情况
              // app.userInfoReadyCallback是在index的onLoad函数中定义的
              // 判断userInfoReadyCallback这个属性是否存在
              // 如果存在,则执行,将用户数据赋值给globalData及index中的data
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    })
  },

但这里有一个问题,如果index页面加载完了,wx.getUserInfo才返回数据怎么办?

因为wx.getUserInfo是通过网络异步获取用户数据,无法保证一定在index页面加载之前就能获取到啊。

这里就用了userInfoReadyCallback函数,这个函数是在index的onLoad函数定义的。

app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }

就是一个简单的赋值函数,将res赋值给index中的data。

而在app.js中的wx.getUserInfo中判断app.userInfoReadyCallback是否存在,如果存在,那么就说明index中的onload函数已经为app写入了userInfoReadyCallback方法,也就是说wx.getUserInfo是通过网络异步获取用户数据成功,实在index加载数据之后,这时就需要调用这个方法,将wx.getUserInfo的返回信息,写入到index中的data。

2、index.js

// index.js
// 获取应用实例
// 用于调用全局状态app.globalData
const app = getApp()

// 注册当前页面index
Page({
  data: {
    motto: 'Hello ',
    userInfo: {},
    hasUserInfo: false,
    // 用于判断微信是否支持button.open-type.getUserInfo用法
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },

  // 生命周期函数,页面加载时
  onLoad: function () {
    console.log('index.js初始化')

    // 判断是否已经获取到用户信息
    if (app.globalData.userInfo) {
      // 已经获取用户信息
      // 将用户信息赋值给userInfo
      // 将hasUserInfo设置为true
      this.setData({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true
      })
      console.log("写入data数据成功")
      this.routerGo()
    } else if (this.data.canIUse){
      // 未获取到用户信息,但微信支持button.open-type.getUserInfo用法
      // 定义app.userInfoReadyCallback函数,
      // 这个函数在app.js调用
      // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
      // 所以此处加入 callback 以防止这种情况
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    } else {
      // 微信不支持button.open-type.getUserInfo用法
      // 在没有 open-type=getUserInfo 版本的兼容处理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        }
      })
    }
  },

  // 绑定自定义点击事件getUserInfo
  // 获取用户信息
  // 回调函数,e就是用户授权后的返回值
  // 若用户授权,用户信息保存在e.detail.userInfo
  // 若用户拒绝,e.detail.userInfo为undefined
  getUserInfo: function(e) {
    console.log("index按钮点击了,调用用户信息")
    console.log(e)
    console.log(e.detail.userInfo)
    // 将用户信息
    app.globalData.userInfo = e.detail.userInfo
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
    this.routerGo()
  },
    
    
   // 事件处理函数
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },

  // 实现页面自动跳转
  routerGo(){
    console.log('跳转函数调用了')

    // 定义一个周期函数interval
    // 判断image图片是否渲染,渲染成功后自动跳转
    let interval=setInterval( ()=> {
      if (wx.createSelectorQuery().select('image')) {
        console.log(wx.createSelectorQuery().select('image'))
        // 跳转
        // 跳转成功后执行回调函数clearInterval
        wx.navigateTo({
          url: './../lession/lession',
          success:()=>{
            console.log(this)
            clearInterval(interval)
          },
        })
      }
    }, 500) 
  }
 
})

(1)获取全局应用app

这样可以通过app.globalData.userInfo获取全局状态。

// index.js
// 获取应用实例
// 用于调用全局状态app.globalData
const app = getApp()

(2)通过Page()注册当前页面。

(3)其中data是index页面的数据

data: {
    motto: 'Hello ',
    userInfo: {},
    hasUserInfo: false,
    // 用于判断微信是否支持button.open-type.getUserInfo用法
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },

(4)然后执行onLoad生命周期函数。

​ 看着复制,其实逻辑很简单。

条件一:判断app.globalData.userInfo中有信息,写入data。

this.routerGo()是我自己写的页面跳转函数,自动跳转到下一个页面。可忽略。

条件二:判断app.globalData.userInfo中没有信息&&微信版本支持button.open-type.getUserInfo(this.data.canIUse)获取用户信息的方式,那么就是说wx.getUserInfo是网络请求,可能会在 Page.onLoad 之后才返回,所以定义app.userInfoReadyCallback方法,在wx.getUserInfo的成功回调中执行。

条件三:判断app.globalData.userInfo中没有信息&&微信版本不支持,那么直接调用wx.getUserInfo()接口。

onLoad函数执行完毕。

 // 生命周期函数,页面加载时
  onLoad: function () {
    console.log('index.js初始化')

    // 判断是否已经获取到用户信息
    if (app.globalData.userInfo) {
      // 已经获取用户信息
      // 将用户信息赋值给userInfo
      // 将hasUserInfo设置为true
      this.setData({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true
      })
      console.log("写入data数据成功")
      this.routerGo()
    } else if (this.data.canIUse){
      // 未获取到用户信息,但微信支持button.open-type.getUserInfo用法
      // 定义app.userInfoReadyCallback函数,
      // 这个函数在app.js调用
      // 由于 wx.getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
      // 所以此处加入 callback 以防止这种情况
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    } else {
      // 微信不支持button.open-type.getUserInfo用法
      // 在没有 open-type=getUserInfo 版本的兼容处理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        }
      })
    }
  },

(5)绑定捕获事件。

// 事件处理函数
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
      
  // 绑定自定义点击事件getUserInfo
  // 获取用户信息
  // 回调函数,e就是用户授权后的返回值
  // 若用户授权,用户信息保存在e.detail.userInfo
  // 若用户拒绝,e.detail.userInfo为undefined
  getUserInfo: function(e) {
    console.log("index按钮点击了,调用用户信息")
    console.log(e)
    console.log(e.detail.userInfo)
    // 将用户信息
    app.globalData.userInfo = e.detail.userInfo
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
    this.routerGo()
  },

(6)自定义方法,实现页面跳转。

routerGo(){
    console.log('跳转函数调用了')

    // 定义一个周期函数interval
    // 判断image图片是否渲染,渲染成功后自动跳转
    let interval=setInterval( ()=> {
      if (wx.createSelectorQuery().select('image')) {
        console.log(wx.createSelectorQuery().select('image'))
        // 跳转
        // 跳转成功后执行回调函数clearInterval
        wx.navigateTo({
          url: './../lession/lession',
          success:()=>{
            console.log(this)
            clearInterval(interval)
          },
        })
      }
    }, 500) 
  }
 类似资料: