ReactLynx 编程思想
ReactLynx 遵循 React 的编程模型,但通过利用 Lynx 提供的双线程运行时,结合自身的编程范式(或规则)来实现更好的性能和用户体验。
你的代码运行在两个线程上
当组件 <HelloComponent /> 被渲染时,你可能会在控制台看到 "Hello" 被打印两次。
这是因为它的代码会在两个线程上运行:主线程和后台线程,它们都是 Lynx 双线程运行时的一部分。
- 主线程负责渲染初始界面和应用后 续的 UI 更新。 这使得用户能尽快看到第一屏内容,同时减轻主线程的负担。
- 后台线程运行完整的 React 运行时,负责处理组件的生命周期和其他副作用。由于无法完全与单线程 React 保持一致,我们有一个修改后的组件生命周期,详见组件生命周期。
并非所有代码都能在两个线程上运行
然而,并非所有代码都能在两个线程上运行。
考虑以下向 GlobalEventEmitter 添加监听器的示例:
当组件 <EventListenerComponent /> 被渲染时,你会看到 "not a function" 的错误。这是因为 lynx 在两个线程渲染了这个组件,但实际上 lynx.getJSModule('GlobalEventEmitter') 不能在主线程执行。
❓ 为什么会出现这个错误?
这仍然与 Lynx 的双线程运行时架构有关,<EventListenerComponent /> 的代码会在两个线程上执行:
-
对于后台线程:
lynx.getJSModule函数是 LynxGlobalEventEmitterAPI 的一部分。因此,在这里执行lynx.getJSModule('GlobalEventEmitter')不会有问题。 -
对于主线程:
相反,
getJSModule函数在主线程上并不存在。因此,当这段代码在主线程上执行时,lynx.getJSModule会被判定为undefined,导致 "not a function" 错误。
某些代码只能在后台线程运行
通常渲染无关的副作用不能在主线程执行,如数据更新、事件监听、定时器、网络请求等。 在主线程执行这些副作用会导致运行时错误。 我们称这种只会在后台线程被执行的代码为 后台专属(background only) 代码。 通过标注后台专属代码,我们能够帮助编译器更好地优化代码,并避免在主线程执行这些副作用。
后台专属代码有以下关键规则:
规则一:满足这些条件之一的代码被视为后台专属代码
Lynx 默认将满足这些条件之一的代码视为后台专属代码:
- 事件处理器(如
bindtap/catchtap) - Effect(如
useEffect/useLayoutEffect) ref属性和useImperativeHandle- 标注
'background only'指令的函数 - 标注
import 'background-only'指令的模块
例如,以下示例中所有这些内含 console.log 的函数都被视为后台专属的。这些函数既不会被打包进主线程代码中,也不会在主线程执行。
遵循这个规则,我们可以知道刚才的 <EventListenerComponent /> 应该把使用 GlobalEventEmitter 的代码移到 useEffect 中。
这样可以确保这部分代码只在后台线程上运行,在那里可以访问到 GlobalEventEmitter API:
规则二:后台专属代码只能在其他后台专属代码中使用
当涉及到依赖关系时,情况会变得更复杂。 简单来说,后台专属代码只能被其他后台专属代码调用。
规则三:只被后台专属代码使用的代码被视为后台专属
通常,元件的事件回调函数会被视为后台专属的。handleTap 虽然没有标记 'background only' 指令,但会被视为后台专属代码,因为它仅在 bindtap 事件中作为处理器被调用。
backgroundOnly 函数也会被视为后台专属的,因为它只在 useEffect 的回调函数中被调用。
例外
受编译器的分析能力和编译期性能所限,这条规则有一些例外。我们会尽力在未来的版本中解决这些问题。
当事件处理函数被作为 props 传递时,必须添加 'background only' 指令,否则编译器无法识别 handleTap 为后台专属代码,并会将其打包进主线程代码中:
当你使用自定义 Hook 时,必须添加 'background only' 指令,否则 backgroundOnly 会被视为非后台专属代码并被打包进主线程代码中。
这是因为编译器不知道 useMount 的回调函数是否只在后台 专属代码中使用。
某些代码只能在主线程运行
正如某些代码(如 GlobalEventEmitter)只能在后台线程工作一样,也有一些代码只能在主线程上执行。
主线程脚本
主线程脚本(MTS)是在主线程上执行的脚本。
关于 MTS 的更多详情,包括使用示例和在主线程处理动画与手势的最佳实践,请参考主线程脚本。
Element PAPI
Lynx 引擎还提供了称为 Element PAPI 的底层 API。
通常,Element PAPI 调用由 ReactLynx 编译生成,你不需要手动编写任何 Element PAPI 代码。