Skip to content

🌱 RN 从零到一(一):React Native 是什么 — 用 React 写原生应用

系列导读:这是「RN 从零到一」系列的第 1 篇。React Native 是 Meta(Facebook)开源的跨平台移动开发框架, 用一套 React + JavaScript/TypeScript 代码同时构建 Android 和 iOS 原生应用。

本文目标:理解 React Native 的定位和原理,完成环境搭建,创建并运行第一个 App。


📊 React Native 速览

维度说明
🏢 出品方Meta(Facebook),2015 年开源
🎯 定位跨平台原生移动应用开发框架
📝 开发语言React + TypeScript(推荐)
📦 当前版本0.76+(新架构已默认启用)
🌐 支持平台Android / iOS(社区支持 Windows / macOS / Web)
⭐ GitHub Star120k+
🏗 架构新架构(Fabric + TurboModules + JSI)

🧩 为什么选 React Native?

跨平台开发的痛点

传统做法:Android 和 iOS 各写一套

Android → Kotlin / Java + XML      → 团队 A
iOS     → Swift / ObjC + Storyboard → 团队 B

问题:
├── 两套代码,维护成本翻倍
├── 功能不同步,容易出现「Android 有但 iOS 没有」
├── 人力资源浪费严重
└── UI 和交互难以统一

React Native 的方案

React Native 方案:一套代码,双端原生

React + TypeScript

   React Native
    ╱        ╲
Android      iOS
(原生视图)  (原生视图)

优势:
├── 一套代码 → Android + iOS 原生应用
├── 学 React 就能写移动端 → Web 前端无缝转型
├── 原生渲染 → 性能接近纯原生 App
├── 热更新 → 不发版也能修 Bug
└── 社区生态丰富(120k+ Star,海量第三方库)

React Native vs 其他方案

方案渲染方式性能开发语言适合场景
React Native原生组件⭐⭐⭐⭐React + TS已有 React 技术栈
Flutter自绘引擎⭐⭐⭐⭐⭐Dart追求极致 UI 一致性
Uni-appWebView / 原生⭐⭐⭐Vue多端小程序 + App
原生开发原生⭐⭐⭐⭐⭐Kotlin/Swift重性能、硬件交互

🛠 1. 环境搭建

前置要求

bash
# 确认 Node.js 版本(需要 >= 18)
node -v   # v20.x.x

# 确认 npm 版本
npm -v    # 10.x.x

# 安装 Watchman(macOS 推荐,用于文件监听)
brew install watchman

方式一:Expo(推荐新手)

Expo 是 React Native 官方推荐的框架,开箱即用,无需配置原生环境:

bash
# 创建 Expo 项目
npx create-expo-app@latest my-rn-app

cd my-rn-app

# 启动开发服务器
npx expo start

然后用手机安装 Expo Go App,扫描终端中的二维码即可预览。

Tips:Expo 现在已经是 React Native 官方推荐的入门方式,绝大多数场景都适用!

方式二:React Native CLI(需要原生环境)

如果需要接入原生模块或已有原生项目,可以使用 CLI 方式:

macOS + iOS 环境

bash
# 1. 安装 Xcode(App Store 下载)
# 确保 Xcode Command Line Tools 已安装
xcode-select --install

# 2. 安装 CocoaPods(iOS 依赖管理)
sudo gem install cocoapods

# 3. 创建项目
npx @react-native-community/cli init MyRNApp

# 4. 运行 iOS
cd MyRNApp
npx react-native run-ios

macOS + Android 环境

bash
# 1. 安装 Android Studio
# 下载地址:https://developer.android.com/studio

# 2. 配置 Android SDK
# Android Studio → Settings → SDK Manager
# 安装 Android 14 (API 34) SDK

# 3. 配置环境变量(~/.zshrc)
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/platform-tools

# 4. 运行 Android
npx react-native run-android

推荐开发工具

工具用途
VS Code代码编辑器(装 React Native Tools 插件)
Expo Go手机端预览 App(扫码即用)
Android StudioAndroid 模拟器 + 调试
XcodeiOS 模拟器 + 调试(仅 macOS)
Flipper / React DevTools调试工具

📁 2. 项目结构解析(Expo 项目)

my-rn-app/
├── app/                          # 📂 页面目录(基于文件的路由)
│   ├── _layout.tsx               # 根布局
│   ├── (tabs)/                   # Tab 导航组
│   │   ├── _layout.tsx           # Tab 布局
│   │   ├── index.tsx             # 首页 Tab
│   │   └── explore.tsx           # 发现 Tab
│   └── +not-found.tsx            # 404 页面
├── assets/                       # 📂 静态资源(图片、字体)
│   ├── images/
│   └── fonts/
├── components/                   # 📂 公共组件
├── constants/                    # 📂 常量定义
│   └── Colors.ts                 # 颜色主题
├── hooks/                        # 📂 自定义 Hook
├── app.json                      # 📄 Expo 配置
├── tsconfig.json                 # 📄 TypeScript 配置
├── package.json                  # 📄 依赖管理
└── babel.config.js               # 📄 Babel 配置

关键文件解读

typescript
// app.json — Expo 配置
{
  "expo": {
    "name": "my-rn-app",
    "slug": "my-rn-app",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/images/icon.png",
    "splash": {
      "image": "./assets/images/splash-icon.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.example.myrnapp"
    },
    "android": {
      "adaptiveIcon": {
        "foregroundImage": "./assets/images/adaptive-icon.png",
        "backgroundColor": "#ffffff"
      },
      "package": "com.example.myrnapp"
    }
  }
}
typescript
// app/_layout.tsx — 根布局
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <Stack>
      <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
      <Stack.Screen name="+not-found" />
    </Stack>
  );
}

🚀 3. 运行项目

Expo 项目启动

bash
# 启动开发服务器
npx expo start

# 显示二维码和菜单:
# › Press s │ switch to Expo Go
# › Press a │ open Android
# › Press i │ open iOS simulator
# › Press w │ open web
# › Press r │ reload app
# › Press j │ open debugger

# 快捷启动命令
npx expo start --ios        # 直接启动 iOS 模拟器
npx expo start --android    # 直接启动 Android 模拟器
npx expo start --web        # 启动 Web 版本

真机调试

📱 iOS 真机:
1. 手机安装 Expo Go App
2. 确保手机和电脑在同一 WiFi
3. 打开 Expo Go,扫描终端二维码

📱 Android 真机:
1. 手机安装 Expo Go App
2. 确保手机和电脑在同一 WiFi
3. 打开 Expo Go,扫描终端二维码

📝 4. 第一个页面

typescript
// app/(tabs)/index.tsx
import { StyleSheet, View, Text, Pressable, Image, Alert } from 'react-native';
import { useState, useCallback } from 'react';

export default function HomeScreen() {
  const [count, setCount] = useState(0);

  const handlePress = useCallback(() => {
    setCount(prev => prev + 1);
    Alert.alert('🎉', '点击了!');
  }, []);

  return (
    <View style={styles.container}>
      <Image
        source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }}
        style={styles.logo}
      />
      <Text style={styles.title}>欢迎使用 React Native</Text>
      <Text style={styles.subtitle}>用 React 写原生应用 🚀</Text>

      <View style={styles.counter}>
        <Text style={styles.count}>{count}</Text>
        <Pressable style={styles.btn} onPress={handlePress}>
          <Text style={styles.btnText}>点我 +1</Text>
        </Pressable>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    padding: 24,
    backgroundColor: '#fff',
  },
  logo: {
    width: 80,
    height: 80,
    marginBottom: 24,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#1a1a1a',
    marginBottom: 8,
  },
  subtitle: {
    fontSize: 16,
    color: '#666',
    marginBottom: 48,
  },
  counter: {
    alignItems: 'center',
  },
  count: {
    fontSize: 64,
    fontWeight: 'bold',
    color: '#6366F1',
  },
  btn: {
    marginTop: 16,
    backgroundColor: '#6366F1',
    paddingHorizontal: 32,
    paddingVertical: 12,
    borderRadius: 12,
  },
  btnText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

⚠️ 注意:React Native 使用 StyleSheet.create() 来定义样式,属性名是驼峰命名 (如 backgroundColor 而不是 background-color),单位不写 px,默认是逻辑像素


🔍 5. React Native 与 React Web 对比

概念React WebReact Native
基础容器<div><View>
文本显示<span> / <p><Text>(文本必须放在 Text 内)
图片<img src=""><Image source=>
输入框<input><TextInput>
按钮<button><Pressable> / <TouchableOpacity>
滚动容器自动滚动<ScrollView> / <FlatList>
CSS 类名className="box"style={styles.box}
样式写法CSS / SassStyleSheet.create({})
布局多种布局默认 Flexbox(且默认纵向)
点击事件onClickonPress
路由react-routerexpo-router / react-navigation
tsx
// React Web 写法:
<div className="card" onClick={handleClick}>
  <img src="logo.png" />
  <span>Hello World</span>
</div>

// React Native 写法:
<View style={styles.card}>
  <Pressable onPress={handlePress}>
    <Image source={require('./logo.png')} />
    <Text>Hello World</Text>
  </Pressable>
</View>

✅ 本篇小结 Checklist


下一篇预告:《核心组件与样式》—— 学习 React Native 的内置组件体系和 Flexbox 布局。


本文是「RN 从零到一」系列第 1 篇,共 10 篇。


📝 作者:NIHoa | 系列:RN从零到一系列 | 更新日期:2025-04-01