雷米已经有几个优点了。我还有一个。
用网桥解释 - 与原生和无网桥对比
尽管名称可能暗示什么,React Native 应用程序不编译为本机代码。 React Native 应用程序在运行时解释 Javascript 代码,并且 React Native 应用程序中的组件更新通过 桥接 到对应的原生视图。这可能会减慢速度并成为瓶颈。
相反,Flutter 应用程序(在发布模式下)编译为本机代码并且不需要桥接器来操作 UI。反过来,至少在理论上,这将提高性能 - 无需往返 本地 来进行简单的 UI 更改。更不用说发布的 Flutter 代码是原生编译的,不涉及任何解释器。
跳舞猴子,跳舞
既然我们知道发布模式的 Flutter 应用程序不需要解释器,也不需要用于 UI 操作的桥梁,那么让我们首先看看这两件事到底是什么。
我们将通过一个高度假设的示例应用来做到这一点。我们的 React Native 应用程序有一个按钮,可以让猴子在屏幕上跳舞。在 React Native 中,我们的按钮和跳舞的猴子组件是用 Javascript 和 React 编写的。
口译员
由于 Javascript 不是 Android 或 iOS 上的一流语言,因此您的 React Native 应用程序包含一个 Javascript 解释器,它解释您的 Javascript 代码在运行时强>。如果没有解释器,您将根本无法使用 Javascript 编写应用程序 - 即使是简单的 console.log('Hello World!') 也行不通。
根据React Native docs,在“大多数情况下”,Javascript 代码将使用 JavascriptCore 进行解释。
桥梁
在底层,React Native 使用原生的 Android Views 和 iOS UIViews 在屏幕上显示 UI 组件(例如跳舞的猴子)。但由于 Android 和 iOS SDK 的 UI 部分不使用 Javascript,因此仅使用 Javascript 无法让猴子跳舞。
这就是一座桥梁发挥作用的地方。桥的另一边是你的 React Native 组件和逻辑,用 Javascript 编写。另一方面,我们有将原生视图呈现到屏幕上的主机 Android/iOS 应用程序。
从现在开始,我们将桥的两侧分别称为Javascript 大陆和原生大陆。
那么,当用户点击我们的“跳舞,猴子,跳舞!”时会发生什么?按钮?
- 原生 Android/iOS 视图调度 onclick 事件,该事件越过桥梁到 Javascript 领域。
- 我们用 Javascript 编写的 onclick 监听器被调用。这是一个简单的调用,用于切换组件内的布尔值。类似于
setState(() {isMonkeyDancing = true}) 或类似的东西。
- React 发现发生了一些变化。它提供了一个更新的UI 元素表示,其中有一只跳舞的猴子。该表示只是描述 UI 更新状态的普通 Javascript 对象树。
- Javascript 对象树被序列化并通过桥发送到本地。
- 宿主应用程序接收序列化的对象树并对其进行反序列化。现在它可以更新原生 Android/iOS 视图以匹配反序列化的 UI 表示。我们的猴子现在在跳舞,我们的用户永远快乐。
所以在这个例子中,一个按钮需要通过桥两次。
实际上,它是三个 - 最初只是简单地呈现一个按钮就是跨桥本身的调用。
在一个不仅仅是一个按钮和一只跳舞的猴子的应用程序中,您可能会更多地越过这座桥。每次你这样做时,它都需要序列化数据并将其从一侧发送到另一侧。
这比仅仅提出 UI 表示并更新 UI直接要慢。此外,与提前编译代码相比,在运行时解释 Javascript 是有代价的。
底线
由于 Flutter 本质上是一个可移植的渲染引擎,因此 Flutter 不需要桥接器来进行 UI 更新。因此,至少在理论上,UI 更新更快。这就是为什么与 React Native 相比,使用 Flutter 构建具有复杂动画或 Flare、SpriteWidget 甚至游戏的应用程序会更有利可图的原因之一。
因为 Flutter 在发布模式下是 AOT 编译的,所以 Flutter 也不需要解释器。这就是 Flutter 和 React Native 的区别。