或许大家在刚开始接触小程序时会有和我同样的疑惑:小程序开发主要使用 WXML、WXSS 和 JavaScript。而 WXML/WXSS 又与 HTML/CSS 十分类似。小程序和 Web 开发如此的相似,那么小程序和 Web 开发又有什么区别呢?或者说小程序有什么独特的地方?
小程序和 Web 开发的区别
网页开发中渲染线程和 JavaScript 线程是互斥 的。即这两个线程不能够穿插执行,必须串行。
当其中一个线程执行时,另一个线程只能挂起等待。这也是 JavaScript线程占用主线程时间过长,可能会导致页面失去响应 的原因。
而在小程序中,二者是分开的,分别运行在不同的线程中,即渲染线程和逻辑线程。这就是本篇文章要终点讨论的地方。
关于其他的不同,请参考官方文档。
渲染线程和逻辑线程
小程序的双线程就是渲染线程和逻辑线程,分别承担 UI 的渲染和执行 JavaScript 代码的工作。如下图所示(图片摘自官方文档):
从图中不难看出,渲染线程使用 WebView 进行 UI 的渲染呈现,逻辑层是用 JavaScript 引擎运行逻辑代码。
小程序主要运行在两大操作系统 iOS 和 Android 的微信客户端,以及用于辅助开发的小程序开发者工具 上。而在不同的运行环境上,WebView 与 JavaScript 引擎也是有所不同的,具体见下表:
| 运行环境 | 渲染层 | 逻辑层 |
|---|---|---|
| iOS | WKWebView | JavaScriptCore |
| 安卓 Android | chromium 定制内核 | V8 |
| 小程序开发者工具 | Chrome WebView | NWJS |
注意:对于安卓环境中逻辑层的 JavaScript 引擎,两个官方文档给的不同:
- 微信官方文档·小程序:V8
- 微信开发社区·小程序开发指南:X5浏览器
通信方式
从上图可以知道,小程序的渲染层和逻辑层之间的通信并不是直接传递数据或事件,而是由 Native(微信客户端) 作为中间媒介进行转发。逻辑层发送网络请求也是经由 Native 转发。
以渲染层和逻辑层通信为例,整个过程如下:
- 渲染层通过与用户的交互触发特定的事件 event;
- 然后 event 被传递给逻辑层;
- 逻辑层通过一系列的逻辑处理、数据请求等操作,叫处理好的 data 传递给渲染层;
- 最后渲染层将 data 渲染为可视化的 UI。
而渲染层和逻辑层通信的这个过程就是典型的事件驱动模式。
了解小程序的通信方式后,想必对关于 setData 的一些优化建议也知其所以然了。例如:
- 尽量减少 setData 的 调用次数和携带的数据大小
- 尽量减少 JavaScript 代码的复杂度
界面渲染
在渲染层,宿主环境会把 WXML 转换成对应的 JavaScript 对象。
在逻辑层发生数据变更时,通过 setData 方法把数据从逻辑层传递到渲染层,经过前后对比,将差异内容应用到原有的 DOM 树上,渲染出更新后的 UI 界面。如图所示:
从宿主环境将 WXML 转换成 JavaScript 对象可以理解另外一个优化:在可以保证功能的前提下使用结构简单的UI。
总结
以上,就是对小程序双线程模型的简单认识。如有错误,望指正。在理解了这些知识后,对我们日后的开发工作会有一定的益处,例如在本文中提到的几点优化建议:
- 尽量减少 setData 的 调用次数和携带的数据大小
- 尽量减少 JavaScript 代码的复杂度
- 在可以保证功能的前提下使用结构简单的 UI
最后,提出一点建议,同时也是笔者以后学习的目标。我们平时对一些技术的 What(是什么)、How(如何用) 往往都聊熟于胸,但对 Why(为什么) 就常常浅尝即止了,希望之后可以问问为什么。共同进步!!!