在开发 Skyline 版小程序时,开发者常对 worklet、shared 及线程机制感到困惑:为何外部变量修改后 worklet 内仍为旧值?shared() 的作用是什么?JS 线程与 UI 线程如何区分?本文将深入解析这些核心概念。
Skyline 双线程模型解析
Skyline 渲染引擎将页面运行拆分为两条独立线程,分工明确:
- JS 线程(业务线程/AppService):负责业务逻辑处理、数据获取及接口请求。
- UI 线程(Worklet 渲染线程):专责渲染、动画及滚动处理,旨在保障 60fps 的流畅体验。
简而言之,JS 线程负责“干活”,UI 线程负责“画面”,两者隔离运行以避免相互阻塞。
JS 线程:业务逻辑的主阵地
绝大多数小程序代码运行在 JS 线程,包括:
- 页面生命周期(onLoad/onReady/onUnload)
- 普通事件绑定(bindtap/bindscroll)
- 网络请求(wx.request)及弹窗(wx.showToast)
- 定时器、setData 操作及普通变量定义
优势与局限:JS 线程具备完整的 API 调用能力,但若执行耗时操作,会导致主线程阻塞,进而引发动画卡顿或交互掉帧。需注意,JS 线程中定义的普通变量和对象具有线程隔离性。
UI 线程:流畅渲染的核心
为确保渲染性能,代码进入 UI 线程执行有严格限制,仅支持以下两种方式:
- WXML 标记:使用
worklet:前缀绑定回调,如<scroll-view worklet:onscrollupdate="onScrollUpdate">。 - 手动投递:通过
runOnUI(fn)()执行函数,且函数体内必须包含'worklet'标记。
function someWorklet(){
'worklet'
// 此处代码运行在 UI 线程
}
runOnUI(someWorklet)()
注意:'worklet' 仅为标记。若直接调用 someWorklet() 而非通过 runOnUI,代码仍将在 JS 线程执行。
UI 线程的限制与规范
出于性能考量,UI 线程存在诸多限制:
- 禁止调用 wx.request、wx.showToast 等大部分 wx API。
- 无法直接获取外部普通变量的最新值(受限于快照机制)。
- 仅允许进行数值计算、插值(interpolate)、修改 shared 共享变量及更新动画样式。
- 若需上报埋点或调用小程序 API,必须使用
runOnJS()切换回 JS 线程。
跨线程通信:快照机制与 Shared 变量
常见误区:普通对象的「快照捕获」
开发者常遇到如下场景:在 runOnUI 前修改了对象属性,但 worklet 内读取的仍是旧值。
const obj = { name: 'skyline' }
function someWorklet() {
'worklet'
console.log(obj.name) // 输出 skyline
}
obj.name = 'change name'
wx.worklet.runOnUI(someWorklet)()
原理:普通变量和对象在通过 runOnUI 投递时,会进行快照拷贝。UI 线程获取的是提交时刻的数据副本,后续 JS 线程对原对象的修改无法同步至 UI 线程。因此,普通变量仅实现一次性数据传递,两边数据互不感知。
解决方案:shared 共享变量
若需实现 JS 线程与 UI 线程的数据实时同步,应使用 worklet.shared()。
const { shared, runOnUI } = wx.worklet
const offset = shared(0)
shared(0) 并非创建数字 0,而是创建一个跨线程共享的“盒子”:
- 读写该变量需通过
.value属性。 - 任一端修改
offset.value,另一端均可立即读取到最新值。
对比总结:
- 普通变量:快照拷贝,一次性传递,数据隔离。
- Shared 变量:共享引用,实时双向同步,适用于滚动联动、吸顶导航等场景。
开发最佳实践
- 优先使用 Worklet:处理滚动联动、吸顶、卡片动画时,建议使用
worklet:onscrollupdate,确保逻辑在 UI 线程运行,避免阻塞业务。 - 正确使用 Shared:涉及跨线程同步的数据(如滚动偏移量),务必使用 shared 变量,避免使用普通变量导致数据不同步。
- 避免引用外部普通对象:Worklet 函数内尽量避免引用外部普通对象,以防因快照机制产生数据不一致的 Bug。
- 合理切换线程:在 UI 线程中如需执行埋点上报或数据请求,请使用
runOnJS切回 JS 线程。 - 明确执行环境:牢记
'worklet'只是标记,必须配合runOnUI才能确保代码在 UI 线程执行。
#微信小程序 #Skyline渲染引擎 #Worklet

