简单说说微信小程序的底层原理

3,180 阅读4分钟

小程序选择了 Hybrid 的渲染方式,将UI渲染跟 JavaScript 的脚本执行分在了两个线程。

双线程模型

小程序的渲染层和逻辑层分别由两个线程管理:

  • 渲染层:界面渲染相关的任务全都在 WebView 线程里执行。一个小程序存在多个界面,所以渲染层存在多个WebView 线程。
  • 逻辑层:采用JsCore 线程运行JS脚本,在这个环境下执行的都是有关小程序业务逻辑的代码。

双线程之间的通信

我们都知道小程序是避免DOM操作,而是采用数据驱动来渲染页面的,那么他到底是怎么通过更改数据来更新DOM呢。

逻辑层和渲染层的通信会由 Native (微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发。通过把 WXML 转化为数据,通过 Native 进行转发,来实现逻辑层和渲染层的交互和通信。

  1. 在渲染层会把WNML转化成Js对象,Js对象会模拟DOM树
  2. 逻辑层更新数据的时候,通过setData方法将数据从逻辑层转发到Native,Native再转发到渲染层
  3. 这时候,比较两虚拟DOM树的差异,最后将差异应用到真实DOM树上,更新页面。

Virtual DOM 相信大家都已有了解,大概是这么个过程:用JS对象模拟DOM树 -> 比较两棵虚拟DOM树的差异 -> 把差异应用到真正的DOM树上。

小程序的生命周期

小程序的生命周期借鉴了Android的生命周期,如果你了解过Android的APP开发,那么理解小程序的就会很简单。

界面线程有四大状态:

  • 初始化状态:初始化界面线程所需要的工作,包括工作机制,基本和我们开发者没有关系,等初始化完毕就向“服务线程”发送初始化完毕信号,然后进入等待传回初始化数据状态。

  • 首次渲染状态:收到“服务线程”发来的初始化数据后(就是 json和js中的data数据),就开始渲染小程序界面,渲染完毕后,发送“首次渲染完毕信号”给服务线程,并将页面展示给用户。

  • 持续渲染状态:此时界面线程继续一直等待“服务线程”通过this.setdata()函数发送来的界面数据,只要收到就重新局部渲染,也因此只要更新数据并发送信号,界面就自动更新。

  • 结束状态:结束渲染。

服务线程五大状态:

  • 初始化状态:无需和其他模块交流,跟小程序开发也没多大关联,此阶段就是启动服务线程所需的基本功能,比如信号发送模块。系统的初始化工作完毕,就调用自定义的onload和onshow, 然后等待界面线程的“界面线程初始化完成”信号。

onload是只会首次渲染的时候执行一次,onshow是每次界面切换都会执行,简单理解,这就是唯一差别。

  • 等待激活状态:接收到“界面线程初始化完成”信号后,将初始化数据发送给“界面线程”,等待界面线程完成初次渲染。

  • 激活状态:收到界面线程发送来的“首次渲染完成”信号后,就进入激活状态既程序的正常运行状态,并调用自定义的onReady()函数。

此状态下就可以通过 this.setData 函数发送界面数据给界面线程进行局部渲染,更新页面。

  • 后台运行状态:如果界面进入后台,服务线程就进入后台运行状态,从目前的官方解读来说,这个状态挺奇怪的,和激活状态是相同的,也可以通过setdata函数更新界面的。毕竟小程序的框架刚推出,应该后续会有很大不同吧。

运行机制

启动

  • 热启动:假如用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需将后台态的小程序切换到前台,这个过程就是热启动;
  • 冷启动:用户首次打开或小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动,即冷启动。

销毁

只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正的销毁。

更新机制

开发者在后台发布新版本之后,无法立刻影响到所有现网用户,但最差情况下,也在发布之后 24 小时之内下发新版本信息到用户。

小程序每次冷启动时,都会检查是否有更新版本,如果发现有新版本,将会异步下载新版本的代码包,并同时用客户端本地的包进行启动,即新版本的小程序需要等下一次冷启动才会应用上。

所以如果想让用户使用最新版本的小程序,可以利用 wx.getUpdateManager 做个检查更新的功能