简单整理小程序原理,方便后面需要时查阅
小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。
框架提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
框架的核心是一个响应的数据绑定系统。
响应的数据绑定
框架的核心是一个响应的数据绑定系统。
整个小程序框架系统分为两部分:视图层(View)和逻辑层(App Service)
框架可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
逻辑层 App Service
小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发者 JavaScript 代码的运行环境以及微信小程序的特有功能。
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。
在 JavaScript 的基础上,我们增加了一些功能,以方便小程序的开发:
增加 App 和 Page 方法,进行程序和页面的注册。
增加 getApp 和 getCurrentPages 方法,分别用来获取 App 实例和当前页面栈。
提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
每个页面有独立的作用域,并提供模块化能力。
注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 window,document 等。
注册程序
小程序 App
App(Object)
App() 函数用来注册一个小程序。接受一个 Object 参数,其指定小程序的生命周期回调等。
App() 必须在 app.js 中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
Object参数说明:
| 属性 | 类型 | 描述 | 触发时机 |
|---|---|---|---|
| onLaunch | Function | 生命周期回调—监听小程序初始化 | 小程序初始化完成时(全局只触发一次) |
| onShow | Function | 生命周期回调—监听小程序显示 | 小程序启动,或从后台进入前台显示时 |
| onHide | Function | 生命周期回调—监听小程序隐藏 | 小程序从前台进入后台时 |
| onError | Function | 错误监听函数 | 小程序发生脚本错误,或者 api 调用失败时触发,会带上错误信息 |
| onPageNotFound | Function | 页面不存在监听函数 | 小程序要打开的页面不存在时触发,会带上页面信息回调该函数 |
| 其他 | Any | 开发者可以添加任意的函数或数据到 Object 参数中,用 this 可以访问 | ——– |
前台、后台定义: 当用户点击左上角关闭,或者按了设备 Home 键离开微信,小程序并没有直接销毁,而是进入了后台;当再次进入微信或再次打开小程序,又会从后台进入前台。需要注意的是:只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正的销毁。
注册页面
页面 Page
Page(Object)
Page(Object) 函数用来注册一个页面。接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
Object 参数说明:
| 属性 | 类型 | 描述 |
|---|---|---|
| data | Object | 页面的初始数据 |
| onLoad | Function | 生命周期回调—监听页面加载 |
| onShow | Function | 生命周期回调—监听页面显示 |
| onReady | Function | 生命周期回调—监听页面初次渲染完成 |
| onHide | Function | 生命周期回调—监听页面隐藏 |
| onUnload | Function | 生命周期回调—监听页面卸载 |
| onPullDownRefresh | Function | 监听用户下拉动作 |
| onReachBottom | Function | 页面上拉触底事件的处理函数 |
| onShareAppMessage | Function | 用户点击右上角转发 |
| onPageScroll | Function | 页面滚动触发事件的处理函数 |
| onTabItemTap | Function | 当前是 tab 页时,点击 tab 时触发 |
| 其他 | Any | 开发者可以添加任意的函数或数据到 Object 参数中,在页面的函数中用 this 可以访问 |
生命周期
下图说明了 Page 实例的生命周期。

路由
页面栈
框架以栈的形式维护了当前的所有页面。 当发生路由切换的时候,页面栈的表现如下:
| 路由方式 | 页面栈表现 |
|---|---|
| 初始化 | 新页面入栈 |
| 打开新页面 | 新页面入栈 |
| 页面重定向 | 当前页面出栈,新页面入栈 |
| 页面返回 | 页面不断出栈,直到目标返回页 |
| Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 |
| 重加载 | 页面全部出栈,只留下新的页面 |
Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):
| 当前页面 | 路由后页面 | 触发的生命周期(按顺序) |
|---|---|---|
| A | A | Nothing happend |
| A | B | A.onHide(), B.onLoad(), B.onShow() |
| A | B (再次打开) | A.onHide(), B.onShow() |
| C | A | C.onUnload(), A.onShow() |
| C | B | C.onUnload(), B.onLoad(), B.onShow() |
| D | B | D.onUnload(), C.onUnload(), B.onLoad(), B.onShow() |
| D (从转发进入) | A | D.onUnload(), A.onLoad(), A.onShow() |
| D(从转发进入) | B | D.onUnload(), B.onLoad(), B.onShow() |
Tips:
- navigateTo, redirectTo 只能打开非 tabBar 页面。
- switchTab 只能打开 tabBar 页面。
- reLaunch 可以打开任意页面。
- 页面底部的 tabBar 由页面决定,即只要是定义为tabBar 的页面,底部都有 tabBar。
- 调用页面路由带的参数可以在目标页面的onLoad中获取。
文件作用域
通过全局函数 getApp() 可以获取全局的应用实例,如果需要全局的数据可以在 App() 中设置,如:
1 | // app.js |
模块化
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports 才能对外暴露接口。1
2
3
4
5
6
7
8
9
10// common.js
function sayHello(name) {
console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}
module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
在需要使用这些模块的文件中,使用 require(path) 将公共代码引入
1 | var common = require('common.js') |
Tips
- tip: require 暂时不支持绝对路径
视图层 View
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。
WXML(WeiXin Markup language) 用于描述页面的结构。
WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
WXSS(WeiXin Style Sheet) 用于描述页面的样式。
组件(Component)是视图的基本组成单元。
WXS 模块
WXS 代码可以编写在 wxml 文件中的 <wxs> 标签内,或以 .wxs 为后缀名的文件内。
模块:
每一个 .wxs 文件和 <wxs> 标签都是一个单独的模块。
每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。
一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现。
注意:<wxs> 模块只能在定义模块的 WXML 文件中被访问到。使用 <include> 或 <import> 时, <wxs> 模块不会被引入到对应的 WXML 文件中。 <template> 标签中,只能使用定义该 <template> 的 WXML 文件中定义的 <wxs> 模块。
自定义组件
类似于页面,一个自定义组件由 json wxml wxss js 4个文件组成。要编写一个自定义组件,首先需要在 json 文件中进行自定义组件声明(将 component 字段设为 true 可这一组文件设为自定义组件):
1 | { |
同时,还要在 wxml 文件中编写组件模版,在 wxss 文件中加入组件样式,它们的写法与页面的写法类似。具体细节和注意事项参见 组件模版和样式 。
插件
插件的开发和使用自小程序基础库版本 1.9.6 开始支持。
插件是对一组 js 接口、自定义组件或页面的封装,用于嵌入到小程序中使用。插件不能独立运行,必须嵌入在其他小程序中才能被用户使用;而第三方小程序在使用插件时,也无法看到插件的代码。因此,插件适合用来封装自己的功能或服务,提供给第三方小程序进行展示和使用。
插件开发者可以像开发小程序一样编写一个插件并上传代码,在插件发布之后,其他小程序方可调用。小程序平台会托管插件代码,其他小程序调用时,上传的插件代码会随小程序一起下载运行。
相对于普通 js 文件或自定义组件,插件拥有更强的独立性,拥有独立的 API 接口、域名列表等,但同时会受到一些限制,如一些 API 无法调用或功能受限。对于一些特殊的接口,如 wx.login 和 wx.requestPayment ,虽然插件不能直接调用,但可以使用 插件功能页 来间接实现。
对于插件开发者,请阅读开发插件章节;对于插件使用者,请阅读使用插件章节。