WeApp: Folder Stucture

20th August 2020 at 2:19pm

主要配置文件

  • app.json:控制小程序的展现、页面路径、网络超时等(链接
  • project.config.json:小程序工具配置,主要设置微信官方出的小程度开发工具(链接
  • pages 路径中每个页面的 JSON 配置文件:配置页面本身的属性(链接

样式文件

app.wxss 是全局样式文件。pages 中的样式文件(如 index.wxss)仅对该页面有效。

JS 文件

app.ts 关心的是整个小程序的生命周期和事件,以及提供整个 app 共享的数据(如下面代码示例中的 globalData);pages 下的 TS 文件(index.ts 等),关心的是一个页面的生命周期和事件。

app.ts

//app.ts
export interface IMyApp {
  userInfoReadyCallback?(res: wx.UserInfo): void
  globalData: {
    userInfo?: wx.UserInfo
  }
}

App<IMyApp>({
  onLaunch() {
    // 展示本地存储能力
    var logs: number[] = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)

    // 登录
    wx.login({
      success(_res) {
        // console.log(_res.code)
        // 发送 _res.code 到后台换取 openId, sessionKey, unionId
      }
    })
    // 获取用户信息
    wx.getSetting({
      success: (res) => {
        if (res.authSetting['scope.userInfo']) {
          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
          wx.getUserInfo({
            success: res => {
              // 可以将 res 发送给后台解码出 unionId
              this.globalData.userInfo = res.userInfo
              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
              // 所以此处加入 callback 以防止这种情况
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res.userInfo)
              }
            }
          })
        }
      }
    })
  },
  globalData: {
  }
})

AppInstance 接口包含了上面所示的 onLaunch 等函数:

interface AppInstance<T extends IAnyObject = {}> {
  /** 生命周期回调—监听小程序初始化
   *
   * 小程序初始化完成时触发,全局只触发一次。
   */
  onLaunch?(options?: ILaunchShowOption): void
  /** 生命周期回调—监听小程序显示
   *
   * 小程序启动,或从后台进入前台显示时
   */
  onShow?(options?: ILaunchShowOption): void
  /** 生命周期回调—监听小程序隐藏
   *
   * 小程序从前台进入后台时
   */
  onHide?(): void
  /** 错误监听函数
   *
   * 小程序发生脚本错误,或者 api
   */
  onError?(/** 错误信息,包含堆栈 */error?: string): void
  /** 页面不存在监听函数
   *
   * 小程序要打开的页面不存在时触发,会带上页面信息回调该函数
   *
   * **注意:**
   * 1. 如果开发者没有添加 `onPageNotFound` 监听,当跳转页面不存在时,将推入微信客户端原生的页面不存在提示页面。
   * 2. 如果 `onPageNotFound` 回调中又重定向到另一个不存在的页面,将推入微信客户端原生的页面不存在提示页面,并且不再回调 `onPageNotFound`。
   *
   * 最低基础库: 1.9.90
   */
  onPageNotFound?(options?: IPageNotFoundOption): void
}

page.ts

页面代码示例:

import { IMyApp } from '../../app'

const app = getApp<IMyApp>()

Page({
  data: {
    motto: '点击 “编译” 以构建',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo'),
  },
  //事件处理函数
  bindViewTap() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad() {
    if (app.globalData.userInfo) {
      this.setData!({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true,
      })
    } else if (this.data.canIUse){
      // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
      // 所以此处加入 callback 以防止这种情况
      app.userInfoReadyCallback = (res) => {
        this.setData!({
          userInfo: res,
          hasUserInfo: true
        })
      }
    } else {
      // 在没有 open-type=getUserInfo 版本的兼容处理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData!({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        }
      })
    }
  }
})

PageInstance 的接口如下:

interface PageInstanceBaseProps<D extends IAnyObject = any> {
  /** 页面的初始数据
   *
   * `data` 是页面第一次渲染使用的**初始数据**。
   *
   * 页面加载时,`data` 将会以`JSON`字符串的形式由逻辑层传至渲染层,因此`data`中的数据必须是可以转成`JSON`的类型:字符串,数字,布尔值,对象,数组。
   *
   * 渲染层可以通过 `WXML` 对数据进行绑定。
   */
  data?: D;

  /** `setData` 函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 `this.data` 的值(同步)。
   *
   * **注意:**
   *
   * 1. **直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致**。
   * 1. 仅支持设置可 JSON 化的数据。
   * 1. 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
   * 1. 请不要把 data 中任何一项的 value 设为 `undefined` ,否则这一项将不被设置并可能遗留一些潜在问题。
   */

  setData?<K extends keyof D>(
    /** 这次要改变的数据
     *
     * 以 `key: value` 的形式表示,将 `this.data` 中的 `key` 对应的值改变成 `value`。
     *
     * 其中 `key` 可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如 `array[2].message`,`a.b.c.d`,并且不需要在 this.data 中预先定义。
     */
    data: D | Pick<D, K> | IAnyObject,
    /** setData引起的界面更新渲染完毕后的回调函数,最低基础库: `1.5.0` */
    callback?: () => void,
  ): void;

  /** 到当前页面的路径,类型为`String`。最低基础库: `1.2.0` */
  route?: string;
}

interface PageInstance<
  D extends IAnyObject = any,
  T extends IAnyObject = any
> extends PageInstanceBaseProps<D> {
  /** 生命周期回调—监听页面加载
   *
   * 页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
   */
  onLoad?(
    /** 打开当前页面路径中的参数 */
    query?: { [queryKey: string]: string },
  ): void;
  /** 生命周期回调—监听页面显示
   *
   * 页面显示/切入前台时触发。
   */
  onShow?(): void;
  /** 生命周期回调—监听页面初次渲染完成
   * 
   * 页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。
   * 
 
   * 注意:对界面内容进行设置的 API 如`wx.setNavigationBarTitle`,请在`onReady`之后进行。
  */
  onReady?(): void;
  /** 生命周期回调—监听页面隐藏
   *
   * 页面隐藏/切入后台时触发。 如 `navigateTo` 或底部 `tab` 切换到其他页面,小程序切入后台等。
   */
  onHide?(): void;
  /** 生命周期回调—监听页面卸载
   *
   * 页面卸载时触发。如`redirectTo`或`navigateBack`到其他页面时。
   */
  onUnload?(): void;
  /** 监听用户下拉动作
   *
   * 监听用户下拉刷新事件。
   * - 需要在`app.json`的`window`选项中或页面配置中开启`enablePullDownRefresh`。
   * - 可以通过`wx.startPullDownRefresh`触发下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致。
   * - 当处理完数据刷新后,`wx.stopPullDownRefresh`可以停止当前页面的下拉刷新。
   */
  onPullDownRefresh?(): void;
  /** 页面上拉触底事件的处理函数
   *
   * 监听用户上拉触底事件。
   * - 可以在`app.json`的`window`选项中或页面配置中设置触发距离`onReachBottomDistance`。
   * - 在触发距离内滑动期间,本事件只会被触发一次。
   */
  onReachBottom?(): void;
  /** 用户点击右上角转发
   *
   * 监听用户点击页面内转发按钮(`<button>` 组件 `open-type="share"`)或右上角菜单“转发”按钮的行为,并自定义转发内容。
   *
   * **注意:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮**
   *
   * 此事件需要 return 一个 Object,用于自定义转发内容
   */
  onShareAppMessage?(
    /** 分享发起来源参数 */
    options?: IShareAppMessageOption,
  ): ICustomShareContent;
  /** 页面滚动触发事件的处理函数
   *
   * 监听用户滑动页面事件。
   */
  onPageScroll?(
    /** 页面滚动参数 */
    options?: IPageScrollOption,
  ): void;

  /** 当前是 tab 页时,点击 tab 时触发,最低基础库: `1.9.0` */
  onTabItemTap?(
    /** tab 点击参数 */
    options?: ITabItemTapOption,
  ): void;

  /** 窗口尺寸改变时触发,最低基础库:`2.4.0` */
  onResize?(
    /** 窗口尺寸参数 */
    options?: IResizeOption,
  ): void;
}