不高兴就手撕小程序官方文档系列(三)

290 阅读7分钟

1. 分包加载

  1. 某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
  2. 在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。
  3. 在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
  4. 目前小程序分包大小有以下限制:
  • 整个小程序所有分包大小不超过 20M
  • 单个分包/主包大小不能超过 2M

1.1 使用分包

  1. 当支持分包的小程序目录结构如:
├── app.js
├── app.json
├── app.wxss
├── packageA
│   └── pages
│       ├── cat
│       └── dog
├── packageB
│   └── pages
│       ├── apple
│       └── banana
├── pages
│   ├── index
│   └── logs
└── utils
  1. 开发者通过app.json subpackage字段声明项目分包结构:
{
  "pages":[
    "pages/index",
    "pages/logs"
  ],
  "subpackages": [
    {
      "root": "packageA",
      "pages": [
        "pages/cat",
        "pages/dog"
      ]
    }, {
      "root": "packageB",
      "name": "pack2",
      "pages": [
        "pages/apple",
        "pages/banana"
      ]
    }
  ]
}
  1. 在subpackage中,每个分包的配置有以下几项: 字段 | 类型 | 说明 | | ----------- | ----------- | ------------------------------------------------------------------------------------------------------ | | root | String | 分包根目录 | | name | String | 分包别名,[分包预下载]时可以使用 | | pages | StringArray | 分包页面路径,相对于分包根目录 | | independent | Boolean | 分包是否是[独立分包] |

1.2 独立分包

  1. 独立分包时小程序中一种特殊类型的分包,可以独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载。

1.2.1 配置方法

  1. 假设小程序目录结构如下:
├── app.js
├── app.json
├── app.wxss
├── moduleA
│   └── pages
│       ├── rabbit
│       └── squirrel
├── moduleB
│   └── pages
│       ├── pear
│       └── pineapple
├── pages
│   ├── index
│   └── logs
└── utils
  1. 开发者通过在app.json的subpackagese字段中对应的分包配置项中定义independent字段声明对应分包为独立分包。
{
  "pages": [
    "pages/index",
    "pages/logs"
  ],
  "subpackages": [
    {
      "root": "moduleA",
      "pages": [
        "pages/rabbit",
        "pages/squirrel"
      ]
    }, {
      "root": "moduleB",
      "pages": [
        "pages/pear",
        "pages/pineapple"
      ],
      "independent": true
    }
  ]
}
  1. 限制
  • 独立分包中不能依赖主包和其他分包中的内容,包括 js 文件、template、wxss、自定义组件、插件等(使用 [分包异步化] 时 js 文件、自定义组件、插件不受此条限制)
  • 主包中的 app.wxss 对独立分包无效,应避免在独立分包页面中使用 app.wxss 中的样式;
  • App 只能在主包内定义,独立分包中不能定义 App,会造成无法预期的行为;
  • 独立分包中暂时不支持使用插件。

1.3 分包预下载

  1. 开发者可以通过配置,在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。对于独立分包,也可以预下载主包。
  2. 预下载分包行为在进入某个页面时触发,通过在app.json增加preloadRule配置来控制
{
  "pages": ["pages/index"],
  "subpackages": [
    {
      "root": "important",
      "pages": ["index"],
    },
    {
      "root": "sub1",
      "pages": ["index"],
    },
    {
      "name": "hello",
      "root": "path/to",
      "pages": ["index"]
    },
    {
      "root": "sub3",
      "pages": ["index"]
    },
    {
      "root": "indep",
      "pages": ["index"],
      "independent": true
    }
  ],
  "preloadRule": {
    "pages/index": {
      "network": "all",
      "packages": ["important"]
    },
    "sub1/index": {
      "packages": ["hello", "sub3"]
    },
    "sub3/index": {
      "packages": ["path/to"]
    },
    "indep/index": {
      "packages": ["__APP__"]
    }
  }
}
  1. proloadRule中,key是页面路径,value是进入此页面的预下载配置 字段 | 类型 | 必填 | 默认值 | 说明 | | -------- | ----------- | -- | ---- | ----------------------------------------------- | | packages | StringArray | 是 | 无 | 进入页面后预下载分包的 root 或 name__APP__ 表示主包。 | | network | String | 否 | wifi | 在指定网络下预下载,可选值为: all: 不限网络 wifi: 仅 wifi 下预下载

  2. 限制

  • 同一个分包中的页面享有共同的预下载 大小限额2M,限额会在打包时校验

2. 框架接口

2.1 小程序App

  1. App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。 属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 | | ---------------------------------------------------------------------------------------------------------------------------------- | -------- | --- | -- | ---------------------- | --------------------------------------------------------------------------------------- | | [onLaunch] | function | | 否 | 生命周期回调——监听小程序初始化。 | | | [onShow] | function | | 否 | 生命周期回调——监听小程序启动或切前台。 | | | [onHide] | function | | 否 | 生命周期回调——监听小程序切后台。 | | | [onError] | function | | 否 | 错误监听函数。 | | | [onPageNotFound]| function | | 否 | 页面不存在监听函数。 | [1.9.90] | | [onUnhandledRejection]| function | | 否 | 未处理的 Promise 拒绝事件监听函数。 | [2.10.0]| | [onThemeChange] | function | | 否 | 监听系统主题变化 | [2.11.0]

  2. getApp()获取小程序全局唯一的App实例

2.2 页面

  1. 注册小程序中的一个页面。接收一个Object类型参数,指定页面的初始数据、生命周期、事件处理函数等。
属性类型默认值必填说明
dataObject页面的初始数据
optionsObject页面的组件选项,同 [Component 构造器]中的 options ,需要基础库版本 [2.10.1]
[behaviors]String Array类似于 mixins 和traits的组件间代码复用机制,参见 [behaviors],需要基础库版本 [2.9.2]
[onLoad](function生命周期回调—监听页面加载
[onShow]function生命周期回调—监听页面显示
[onReady]function生命周期回调—监听页面初次渲染完成
[onHide]function生命周期回调—监听页面隐藏
[onUnload]function生命周期回调—监听页面卸载
[onPullDownRefresh]function监听用户下拉动作
[onReachBottom]function页面上拉触底事件的处理函数
[onShareAppMessage]function用户点击右上角转发
[onShareTimeline]function用户点击右上角转发到朋友圈
[onAddToFavorites]function用户点击右上角收藏
[onPageScroll]function页面滚动触发事件的处理函数
[onResize]function页面尺寸改变时触发,详见 [响应显示区域变化]
[onTabItemTap]function当前是 tab 页时,点击 tab 时触发
[onSaveExitState]function页面销毁前保留状态回调

2.3 自定义组件

  1. Component:创建自定义组件,接收一个Object类型的参数。 定义段 | 类型 | 是否必填 | 描述 | | ---------------- | ------------ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------ | | properties | Object Map | 否 | 组件的对外属性,是属性名到属性设置的映射表 | | | data | Object | 否 | 组件的内部数据,和 properties 一同用于组件的模板渲染 | | | observers | Object | 否 | 组件数据字段监听器,用于监听 properties 和 data 的变化,参见 [数据监听器]| [2.6.1] | | methods | Object | 否 | 组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见 [组件间通信与事件]| | | behaviors | String Array | 否 | 类似于 mixins 和traits的组件间代码复用机制,参见 [behaviors] | | | created | Function | 否 | 组件生命周期函数 - 在组件实例刚刚被创建时执行,注意此时不能调用 setData ) | | | attached | Function | 否 | 组件生命周期函数 - 在组件实例进入页面节点树时执行) | | | ready | Function | 否 | 组件生命周期函数 - 在组件布局完成后执行) | | | moved | Function | 否 | 组件生命周期函数 - 在组件实例被移动到节点树另一个位置时执行) | | | detached | Function | 否 | 组件生命周期函数 - 在组件实例被从页面节点树移除时执行) | | | relations | Object | 否 | 组件间关系定义,参见 [组件间关系] | | | externalClasses | String Array | 否 | 组件接受的外部样式类,参见 [外部样式类] | | | options | Object Map | 否 | 一些选项(文档中介绍相关特性时会涉及具体的选项设置,这里暂不列举) | | | lifetimes | Object | 否 | 组件生命周期声明对象,参见 [组件生命周期] | | pageLifetimes | Object | 否 | 组件所在页面的生命周期声明对象,参见 [组件生命周期] | | definitionFilter | Function | 否 | 定义段过滤器,用于自定义组件扩展,参见 [自定义组件扩展] |

  2. 实例代码

Component({

  behaviors: [],
  properties: {
    myProperty: { // 接收传递的属性/值
      type: String,
      value: ''
    },
    myProperty2: String // 简化的定义方式
  },

  data: {}, // 私有数据,可用于模板渲染

  lifetimes: {
    // 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
    attached: function () { },
    moved: function () { },
    detached: function () { },
  },

  // 生命周期函数,可以为函数,或一个在 methods 段中定义的方法名
  attached: function () { }, // 此处 attached 的声明会被 lifetimes 字段中的声明覆盖
  ready: function() { },

  pageLifetimes: {
    // 组件所在页面的生命周期函数
    show: function () { },
    hide: function () { },
    resize: function () { },
  },

  methods: {
    onMyButtonTap: function(){
      this.setData({
        // 更新属性和数据的方法与更新页面数据的方法类似
      })
    },
    // 内部方法建议以下划线开头
    _myPrivateMethod: function(){
      // 这里将 data.A[0].B 设为 'myPrivateData'
      this.setData({
        'A[0].B': 'myPrivateData'
      })
    },
    _propertyChange: function(newVal, oldVal) {

    }
  }

})

2.4 模块化

  1. require
    • 引入模块。返回模块通过module.exports或exports暴露的接口
    • 实例代码
    const common = require('common.js')
  1. module
    • 当前模块对象
    • 示例代码
// common.js
function sayHello(name) {
 console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
 console.log(`Goodbye ${name} !`)
}

module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye