小程序架构
小程序双线程架构模型及通信机制
问题
描述小程序的架构设计,解释为什么采用这种架构。
解答
双线程架构
小程序采用双线程模型,将渲染层和逻辑层分离:
┌─────────────────────────────────────────────────────┐
│ 视图层 │
│ (Render Thread) │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ WebView │ │ WebView │ │ WebView │ ... │
│ │ (页面1) │ │ (页面2) │ │ (页面3) │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└──────────────────────┬──────────────────────────────┘
│
│ setData / 事件
▼
┌─────────────────────────────────────────────────────┐
│ Native 层 │
│ (JSBridge / 微信客户端) │
└──────────────────────┬──────────────────────────────┘
│
│ 数据 / 回调
▼
┌─────────────────────────────────────────────────────┐
│ 逻辑层 │
│ (Logic Thread) │
│ ┌─────────────────┐ │
│ │ JsCore / │ │
│ │ V8 引擎 │ │
│ └─────────────────┘ │
│ App Service │
└─────────────────────────────────────────────────────┘
各层职责
// 逻辑层 - 运行在 JsCore/V8 中
// 负责业务逻辑、数据处理、API 调用
Page({
data: {
list: []
},
onLoad() {
// 调用微信 API(通过 Native 层)
wx.request({
url: 'https://api.example.com/data',
success: (res) => {
// 通过 setData 将数据发送到渲染层
this.setData({ list: res.data })
}
})
},
// 接收渲染层的事件
handleTap(e) {
console.log('点击事件', e)
}
})
<!-- 渲染层 - 运行在 WebView 中 -->
<!-- 负责页面渲染、用户交互 -->
<view class="container">
<view
wx:for="{{list}}"
wx:key="id"
bindtap="handleTap"
>
{{item.name}}
</view>
</view>
通信机制
// setData 的工作流程
this.setData({ count: 1 })
// 1. 逻辑层:数据序列化为 JSON 字符串
// 2. Native 层:通过 JSBridge 传输数据
// 3. 渲染层:反序列化,执行 diff,更新 DOM
// 性能优化:减少 setData 调用次数和数据量
// 错误示范
this.setData({ a: 1 })
this.setData({ b: 2 })
this.setData({ c: 3 })
// 正确做法
this.setData({ a: 1, b: 2, c: 3 })
// 只更新需要的字段
this.setData({
'list[0].name': 'new name', // 路径更新
'obj.key': 'value'
})
为什么采用双线程
// 1. 安全性 - 逻辑层无法直接操作 DOM
// 开发者无法执行以下操作:
document.getElementById('xxx') // 不可用
window.location.href = 'xxx' // 不可用
// 2. 性能 - 渲染和逻辑并行执行
// 逻辑层计算不会阻塞渲染
// 多个 WebView 可以预加载
// 3. 管控 - 平台可以控制 API 能力
// 所有能力都通过 Native 层提供
wx.request() // 网络请求
wx.getLocation() // 位置信息
wx.scanCode() // 扫码
与传统 Web 的对比
| 特性 | 小程序 | 传统 Web |
|---|---|---|
| 线程模型 | 双线程 | 单线程 |
| DOM 操作 | 不可直接操作 | 可直接操作 |
| 渲染引擎 | WebView | 浏览器 |
| JS 引擎 | JsCore/V8 | 浏览器内置 |
| 通信方式 | 异步序列化 | 同步 |
关键点
- 双线程架构:渲染层(WebView)和逻辑层(JsCore)分离运行
- 通信机制:通过 Native 层的 JSBridge 进行数据传输,setData 是异步的
- 安全管控:逻辑层无法直接操作 DOM,所有能力由平台提供
- 性能代价:跨线程通信需要序列化,频繁 setData 会影响性能
- 每个页面对应一个 WebView,支持多页面预加载
目录