跨平台移动开发框架对比:Flutter / React Native / uni-app
一句话总结
Flutter — 自绘引擎,像素级一致,控制力最强 React Native — 原生组件映射,Web 团队无缝上手 uni-app — Vue 语法,一套代码发布全平台,国内小程序生态最强
一、基本信息
| Flutter | React Native | uni-app | |
|---|---|---|---|
| 出品方 | Meta(Facebook) | DCloud | |
| 开源时间 | 2017 | 2015 | 2018 |
| 开发语言 | Dart | JavaScript / TypeScript | JavaScript / TypeScript(Vue 语法) |
| 框架语法 | Widget 树(声明式) | React JSX + Hooks | Vue 2 / Vue 3(Options API / Composition API) |
| 上手门槛 | 需要学 Dart + Widget 概念 | 会 React 即可 | 会 Vue 即可,门槛最低 |
二、渲染机制
这是三者最本质的区别。
| Flutter | React Native | uni-app | |
|---|---|---|---|
| 渲染方式 | 自绘引擎(Impeller/Skia),自己画每个像素 | 映射为平台原生组件 | 多端编译:App 端用原生渲染(weex 引擎)或 WebView;小程序端编译为各平台小程序代码;H5 端就是 Web |
| 两端一致性 | 像素级一致(自己画的当然一样) | 基本一致,细节可能有平台差异 | App 端基本一致;小程序端受各平台限制 |
| 平台融合感 | 需要手动适配平台风格 | 天然原生风格 | App 端接近原生;小程序端就是原生小程序 |
类比
- Flutter:自带画板和画笔,在哪都自己画
- React Native:翻译官,把你说的话翻译给平台原生组件听
- uni-app:万能适配器,同一个插头根据不同国家的插座自动转换形状
三、平台覆盖
| 平台 | Flutter | React Native | uni-app |
|---|---|---|---|
| iOS | 官方支持 | 官方支持 | 支持 |
| Android | 官方支持 | 官方支持 | 支持 |
| 微信小程序 | 不支持 | 不支持 | 支持 |
| 支付宝/百度/抖音/QQ 小程序 | 不支持 | 不支持 | 支持 |
| 快应用 | 不支持 | 不支持 | 支持 |
| H5(移动 Web) | 官方支持(体验一般) | 第三方(React Native Web) | 支持 |
| 桌面(Windows/macOS/Linux) | 官方支持 | 社区方案 | 不支持 |
uni-app 的杀手锏
国内市场绑不开微信小程序。Flutter 和 React Native 都不能直接编译为小程序,uni-app 可以一套代码同时发布到 App + 各家小程序 + H5,这在国内是巨大的优势。
四、性能
| Flutter | React Native | uni-app | |
|---|---|---|---|
| App 端性能 | 最接近原生,Impeller 引擎直接绘制 | 接近原生(新架构 JSI 直接调用) | 取决于渲染模式:原生渲染接近 RN,WebView 模式较差 |
| 动画流畅度 | 最佳,渲染引擎直接控制 | 需要 Reanimated 库才能达到流畅 | 复杂动画是短板 |
| 启动速度 | AOT 编译为机器码,快 | JS 引擎加载,稍慢 | 首次启动较慢(需要初始化运行环境) |
| 列表性能 | 优秀 | 优秀(FlatList 虚拟化) | 长列表是已知痛点,需要优化 |
| 包体积 | ~5-8MB(自带引擎) | ~2-4MB | ~5-10MB(自带运行时) |
简单排序
纯 App 性能:Flutter ≥ React Native > uni-app(原生渲染)> uni-app(WebView)
五、开发体验
| Flutter | React Native | uni-app | |
|---|---|---|---|
| 热重载 | 极快,状态保持 | 快,状态保持 | 支持,速度一般 |
| IDE | Android Studio / VS Code | VS Code | HBuilderX(官方 IDE)/ VS Code |
| 调试工具 | DevTools(优秀) | React DevTools / Expo Dev Tools | HBuilderX 内置调试 |
| 类型安全 | Dart 强类型 + 空安全 | TypeScript 可选 | TypeScript 可选 |
| 包管理 | pub.dev | npm | npm + DCloud 插件市场 |
| 文档质量 | 英文文档优秀 | 英文文档优秀 | 中文文档齐全,对国内开发者最友好 |
六、生态与社区
| Flutter | React Native | uni-app | |
|---|---|---|---|
| 全球社区 | 大,增长快 | 最大 | 小(主要在国内) |
| 国内社区 | 活跃 | 活跃 | 最活跃,中文资源最多 |
| 插件/组件 | pub.dev ~4 万+ | npm 百万级 | DCloud 插件市场 + npm |
| UI 组件库 | 内置 Material/Cupertino | Paper、gluestack-ui、Tamagui | uView、uni-ui、TuniaoUI |
| 原生能力扩展 | Platform Channel(需写原生代码) | Expo Modules / Native Modules | 原生插件市场(很多现成的,不需要自己写) |
| 状态管理 | Riverpod、Bloc | Zustand、Redux Toolkit | Pinia、Vuex |
| SSR 框架 | 无成熟方案 | Next.js(Web 端) | 不涉及 |
七、代码风格对比
同一个计数器,三种写法:
Flutter(Dart)
class Counter extends StatefulWidget {
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int count = 0;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('点了 $count 次', style: TextStyle(fontSize: 24)),
ElevatedButton(
onPressed: () => setState(() => count++),
child: Text('点击'),
),
],
),
);
}
}React Native(TypeScript)
import { useState } from 'react'
import { View, Text, Button, StyleSheet } from 'react-native'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<View style={styles.container}>
<Text style={styles.text}>点了 {count} 次</Text>
<Button title="点击" onPress={() => setCount(count + 1)} />
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
text: { fontSize: 24, marginBottom: 16 },
})uni-app(Vue 3)
<template>
<view class="container">
<text class="text">点了 {{ count }} 次</text>
<button @click="count++">点击</button>
</view>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<style scoped>
.container { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; }
.text { font-size: 24px; margin-bottom: 16px; }
</style>直观感受
- Flutter:嵌套最深,Widget 套 Widget,括号多
- React Native:JSX 结构清晰,JS 风格
- uni-app:最接近写网页的体验——HTML 模板 + CSS 样式 + JS 逻辑,前端开发者最熟悉
八、商业与就业
| Flutter | React Native | uni-app | |
|---|---|---|---|
| 国内就业 | 中大厂有岗位,增长中 | 岗位较多 | 外包/中小公司/创业团队大量使用 |
| 海外就业 | 岗位增长快 | 最多 | 几乎没有 |
| 典型用户 | 阿里(闲鱼)、字节、Google | Meta、Shopify、Microsoft | 大量国内中小企业、政务应用 |
| 适合创业团队 | 适合(跨平台一致) | 适合(生态成熟) | 最适合(一套代码打全平台,省人省钱) |
九、选型建议
按团队背景选
| 团队背景 | 推荐 | 原因 |
|---|---|---|
| Vue 开发者 | uni-app | 语法零成本迁移 |
| React 开发者 | React Native | 知识完全复用 |
| 移动端原生开发者 | Flutter | Dart OOP 风格接近 Swift/Kotlin |
| 全栈新手 | uni-app | 学习成本最低,文档全中文 |
按项目需求选
| 需求 | 推荐 | 原因 |
|---|---|---|
| 必须发布微信小程序 | uni-app | Flutter 和 RN 都不支持 |
| App + 各家小程序 + H5 全平台覆盖 | uni-app | 唯一能一套代码打全平台的 |
| 追求极致性能和动画 | Flutter | 自绘引擎,控制力最强 |
| 两端 UI 像素级一致 | Flutter | 自己画的当然一样 |
| 融入平台原生风格 | React Native | 本来就是原生组件 |
| Web 和 Mobile 共享代码 | React Native | React 生态无缝复用 |
| 预算有限、快速上线 | uni-app | 开发效率最高,插件市场现成方案多 |
| 海外市场 | Flutter 或 React Native | uni-app 海外生态几乎为零 |
| 桌面端也要覆盖 | Flutter | 官方支持 Windows/macOS/Linux |
一句话版
Quote
- 要小程序 → uni-app,没得选
- 要极致体验 → Flutter
- 要Web 团队快速出活 → React Native(React 系)或 uni-app(Vue 系)
- 要省钱打全平台 → uni-app
- 要海外市场 → Flutter 或 React Native