张啸


世界上最快乐的事,莫过于为理想而奋斗。


微信(1) 小程序初体验

微信小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开。这也体现了“用完即走”的理念,用户无需担心安装应用过多的问题。应用将无处不在,随时可用,但又无须安装卸载。

本文对微信小程序的架构进行了简要的介绍,让我们尽可能对小程序有个全局的认知,包括小程序的框架、目录结构、开发步骤等等。

小程序的开发实际上就是不同页面的展示(视图),以及实现“页面上用户交互事件”、“页面间切换逻辑”、“数据存储及网络调用”等事务和逻辑处理的过程。


一、小程序执行的生命周期

一个完整的小程序执行的生命周期如下所示:

1
2
3
4
5
6
app.onLaunch -> app.onShow -> page1.onLoad -> page1.onShow -> page1.onReady
(打开程序,第一个页面page1加载完成)
-> page1.onHide -> page2.onLoad -> page2.onShow -> page2.onReady
(从第一个页面新打开page2)
-> page2.onUnload -> page1.onShow -> ... -> app.onUnload
(关闭page2,返回page1,...退出小程序)

一个page的生命周期从onLoad开始,整个生命周期内onLoadonReadyonUnload这三个事件仅执行一次,而onHideonShow在每次页面隐藏和显示时都会触发。当用户手动触发退出时,小程序仅触发app.onHide,下次进入小程序时会触发app.onShow以及当前page.onShow。仅当小程序在后台运行超过一定时间未被唤醒、或者用户手动在小程序的控制栏里点击退出程序、或者小程序内存占用过大被关闭时,小程序将被销毁,会触发app.onUnload事件。


二、小程序的线程架构

每个小程序分为两个线程,viewappServer。其中view负责解析渲染页面(wxmlwxss),而appServer线程负责运行jsappServer线程运行在jsCore中(安卓下运行在X5中,开发工具中运行在nwjs中)。由于js不跑在web-view里,就不能直接操纵DOM和BOM,这就是小程序没有window全局变量的原因。

  • view线程

    wxss + wxml

    ios:safari

    Android:X5浏览器

    开发工具:chrome

  • appServer线程

    JS

    ios:JavaScriptCore

    Android:X5内核

    开发工具:nwjs


三、小程序开发步骤

理解小程序的线程架构后,我们可以归纳出一个小程序开发的主要步骤,涉及两大步骤:

  • 创建小程序实例(定义、配置及页面执行关联)。即编写3个app前缀的文件,它们共同描述了整个小程序主体逻辑、生命周期及页面构成、样式等。小程序实例将由appServer线程执行。

  • 创建页面(页面结构和事务处理逻辑)。在小程序中一个完整的页面(page)是由.js.json.wxml.wxss这四个文件组成,每个界面.js.wxml是必选项,其他两项是可选项。小程序页面由view线程执行。


四、MINA框架

微信团队为小程序提供的框架命名为MINA应用框架。MINA框架通过封装微信客户端提供的文件系统、网络通信、任务管理、数据安全等基础功能,对上层提供一整套JavaScript API,让开发者能够非常方便地使用微信客户端提供的各种基础功能与能力,快速构建一个应用。

小程序框架示意图如下

小程序MINA框架示意图

通过框架图我们可以看到两大部分:在页面视图层,wxml是MINA提供的一套类似html标签的语言以及一系列基础组件。开发者使用wxml文件来搭建页面的基本视图结构,使用wxss文件来控制页面的展现样式。AppService应用逻辑层时MINA的服务中心,由微信客户端启用异步线程单独加载运行。页面渲染所需的数据、页面交互处理逻辑都在AppService中实现。MINA框架中的AppService使用JavaScript来编写交互逻辑、网络请求、数据处理,但不能使用JavaScript中的DOM操作。小程序中的各个页面可以通过AppService实现数据管理、网络通信、应用生命周期管理和页面路由。

MINA框架为页面组件提供了bindtapbindtouchstart等事件监听相关的属性,来与AppService中的事件处理函数绑定在一起,实现页面向AppService层同步用户交互数据。MINA框架同时提供了很多方法将AppService中的数据与页面进行单向绑定,当AppService中的数据变更时,会主动触发对应页面组件的重新渲染。MINA使用virtual-dom技术,加快了页面的渲染效率。

框架的核心是一个响应的数据绑定系统,它让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。我们通过下面的例子来看一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- This is our View -->
<view> Hello {{ name }}!</view>
<button bindtap="changeName">Click Me!</button>

// This is out App Service
// This is our data.
var helloData = {
name: 'WeChat'
}

Page({
data: helloData,
changeName: function(e) {
this.setData({
name: 'MINA'
})
}
})

开发者通过框架将逻辑层数据中的name与视图层的name进行了绑定,所以在页面一打开的时候会显示“Hello WeChat!”。

当点击按钮的时候,视图层会发送changeName的事件给逻辑层,逻辑层找到对应的事件处理函数。

逻辑层执行了setData的操作,将nameWeChat变为MINA,因为该数据和视图层已经绑定了,从而视图层会自动改变为“Hello MINA!”。

微信小程序不仅在底层架构的运行机制上做了大量的优化,还在重功能(如page切换、tab切换、多媒体、网络连接等)上使用接近于native的组件承载。

综上所述,微信小程序MINA有着接近原生App的运行速度,做了大量的框架层面的优化设计,对Android端和IOS端做出了高度一致的呈现,并且准备了完备的开发和调试工具。


五、逻辑层

对于微信小程序而言,逻辑层就是所有.js脚本文件的集合。微信小程序在逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

微信小程序开发框架的逻辑层是由JavaScript编写,在JavaScript的基础上,微信团队做了一些适当的修改,以便更高效地开发小程序。主要的修改包括:

  • 增加apppage方法,进行程序和页面的注册

  • 提供丰富的API,如扫一扫、支付等微信特有能力

  • 每个页面有独立的作用域,并提供模块化能力

小程序逻辑层由js编写,但并非运行在浏览器中,所以JavaScript在Web中的一些能力都将无法使用,比如documentwindow等,这也给我们的开发带来相应的挑战。

开发者编写的所有代码最终将会打包成一份JavaScript,并在小程序启动时运行,直到小程序销毁。这类似于ServiceWorker或Webpack,所以逻辑层也称之为AppService。


六、视图层

框架的视图层由WXML(WeiXin Markup Language)与WXSS(WeiXin Style Sheet)编写,由组件来进行展示。对于微信小程序而言,视图层就是所有的.wxml文件与.wxss文件的集合:

  • .wxml文件用于描述页面的结构

  • .wxss文件用于描述页面的样式

微信小程序在逻辑层将数据进行处理后发送给视图层展现出来,同时接受视图层的事件反馈。

视图层以给定的样式展现数据并反馈给逻辑层,而数据展现是以组件来进行的。组件(Component)是视图的基本组成单元。


七、数据层

数据层包括临时数据或缓存、文件存储、网络存储与调用。

1. 页面临时数据或缓存

Page()中,我们要使用setData函数来将数据从逻辑层发送到视图层,同时改变对应的this.data的值。

注意

  • 直接修改this.data无效,无法改变页面的状态,还会造成数据不一致

  • 单次设置的数据不能超过1024KB,请尽量避免一次设置过多的数据

setData()函数的参数接受一个对象。以keyvalue的形式表示将this.data中的key对应的值改变成value。其中key可以非常灵活,包括以数据路径的形式给出,如array[2].messagea.b.c.d,并且无须在this.data中预先定义。

2. 文件存储(本地存储)

使用数据API接口,如下所示:

  • wx.getStorage:获取本地数据缓存

  • wx.setStorage:设置本地数据缓存

  • wx.clearStorage:清理本地数据缓存

3. 网络存储或调用

上传或下载文件API接口如下:

  • wx.request:发起网络请求

  • wx.uploadFile:上传文件

  • wx.downloadFile:下载文件

调用URL的API接口如下:

  • wx.navigateTo:新窗口打开页面

  • wx.redirectTo:原窗口打开页面


八、小程序加载运行

整个微信小程序、用户使用加载的流程示意图如下所示:

小程序发布与运行加载的流程

小程序通过微信团队审核发布后,会同步到微信云端。最终用户通过某个入口,关注到该小程序。第一次运行时要经过短暂的代码下载过程(将所有资源下载到本地),即可在用户的微信中运行。

小程序在用户的微信中启动,相当于开启一个webview,这与HTML5不一样,在一定的时间内除非手动关闭,即使返回打开另一个小程序,原来的小程序也一直以后台的形式运行在内存里,即在后台运行。

小程序的版本更新将在启动时进行。首先与微信客户端版本进行对比是否有新版本,若有则小程序更新后再运行;否则,直接使用本地资源运行。


参考文献

  1. 《小程序,巧应用(微信小程序开发实战)——熊普江 谢宇华》