React Native 完全入门:从原理到实战


一、React Native 是什么

React Native(简称 RN)是 Facebook 开源的跨平台移动应用开发框架,让你用 JavaScript 和 React 语法编写原生 iOS 和 Android 应用。

核心特点:

  • 真原生渲染 :不是 WebView,而是调用原生 UI 组件 - 热更新 :无需重新打包,线上修复 bug - 跨平台 :一套代码,iOS 和 Android 共用 80%+ 逻辑 - React 生态:复用 React 的组件化、状态管理等能力

与其他方案对比:

方案 渲染方式 性能 开发体验
原生开发 原生 最优 需学 Swift/Kotlin
React Native 原生 接近原生 JavaScript + React
Flutter 自绘引擎 接近原生 Dart 语言
Hybrid(Cordova) WebView 较差 Web 技术栈

二、React Native 的工作原理

2.1 整体架构

scss 复制代码
┌─────────────────────────────────────┐
│      JavaScript 层(业务逻辑)       │
│      (React 组件、状态管理)          │
└──────────────┬──────────────────────┘
               │ Bridge(消息通信)
┌──────────────┴──────────────────────┐
│      Native 层(原生模块)           │
│      (UI 渲染、网络、存储等)         │
└─────────────────────────────────────┘

三层结构:

  1. JavaScript 层 :运行在 JavaScriptCore(iOS)或 Hermes(Android)引擎中,执行 React 代码 2. Bridge :JS 和 Native 之间的消息通道,传递 JSON 数据 3. Native 层:iOS 用 Objective-C/Swift,Android 用 Java/Kotlin,负责实际渲染和系统调用

2.2 渲染流程

javascript 复制代码
// 1. 你写的 JSX
<View style={{ flex: 1 }}>
  <Text>Hello RN</Text>
</View>

// 2. React 转成虚拟 DOM
{
  type: 'View',
  props: { style: { flex: 1 } },
  children: [
    { type: 'Text', props: {}, children: ['Hello RN'] }
  ]
}

// 3. Bridge 传给 Native
{
  "type": "createView",
  "viewId": 1,
  "viewType": "RCTView",
  "props": { "flex": 1 }
}

// 4. Native 创建真实 UI
UIView *view = [[UIView alloc] init];  // iOS
// 或
View view = new View(context);         // Android

2.3 Bridge 通信

JS 调用 Native:

javascript 复制代码
// JS 端
import { NativeModules } from 'react-native';
const { ToastModule } = NativeModules;

ToastModule.show('Hello', ToastModule.SHORT);

Native 实现(iOS):

objective-c 复制代码
// ToastModule.m
#import <React/RCTBridgeModule.h>

@interface ToastModule : NSObject <RCTBridgeModule>
@end

@implementation ToastModule

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(show:(NSString *)message duration:(NSInteger)duration) {
  dispatch_async(dispatch_get_main_queue(), ^{
    // 显示 Toast
  });
}

@end

Native 调用 JS:

objective-c 复制代码
// Native 端
[self.bridge enqueueJSCall:@"RCTDeviceEventEmitter"
                    method:@"emit"
                      args:@[@"onNetworkChange", @{@"type": @"wifi"}]
                completion:NULL];
javascript 复制代码
// JS 端
import { NativeEventEmitter, NativeModules } from 'react-native';

const eventEmitter = new NativeEventEmitter(NativeModules.ToastModule);
eventEmitter.addListener('onNetworkChange', (event) => {
  console.log('网络变化:', event.type);
});

三、从零搭建 React Native 项目

3.1 环境准备

安装依赖:

bash 复制代码
# macOS(开发 iOS 需要)
brew install node watchman
sudo gem install cocoapods

# 安装 React Native CLI
npm install -g react-native-cli

安装 Xcode(iOS)或 Android Studio(Android)。

3.2 创建项目

bash 复制代码
npx react-native init MyApp
cd MyApp

目录结构:

bash 复制代码
MyApp/
├── android/          # Android 原生代码
├── ios/              # iOS 原生代码
├── node_modules/
├── App.tsx           # 入口组件
├── index.js          # 注册入口
├── package.json
└── metro.config.js   # 打包配置

3.3 运行项目

bash 复制代码
# iOS
npx react-native run-ios

# Android(需先启动模拟器或连接真机)
npx react-native run-android

四、核心组件

4.1 View 和 Text

javascript 复制代码
import { View, Text, StyleSheet } from 'react-native';

function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hello React Native</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5f5'
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333'
  }
});

4.2 Image

javascript 复制代码
<Image
  source={{ uri: 'https://example.com/image.png' }}
  style={{ width: 200, height: 200 }}
  resizeMode="cover"
/>

// 本地图片
<Image source={require('./assets/logo.png')} />

4.3 ScrollView 和 FlatList

javascript 复制代码
// ScrollView:适合少量数据
<ScrollView>
  {data.map(item => <Text key={item.id}>{item.name}</Text>)}
</ScrollView>

// FlatList:适合长列表,支持虚拟滚动
<FlatList
  data={data}
  keyExtractor={item => item.id}
  renderItem={({ item }) => <Text>{item.name}</Text>}
  onEndReached={loadMore}
  onEndReachedThreshold={0.5}
/>

4.4 TouchableOpacity

javascript 复制代码
<TouchableOpacity
  onPress={() => console.log('点击')}
  activeOpacity={0.7}
>
  <Text>点我</Text>
</TouchableOpacity>

五、样式与布局

5.1 Flexbox 布局

RN 默认使用 Flexbox,但有些差异:

javascript 复制代码
// 默认 flexDirection 是 column(Web 是 row)
<View style={{ flexDirection: 'row' }}>
  <View style={{ flex: 1, backgroundColor: 'red' }} />
  <View style={{ flex: 2, backgroundColor: 'blue' }} />
</View>

5.2 尺寸单位

RN 没有 pxrem,只有无单位数字(对应设备独立像素 dp/pt):

javascript 复制代码
<View style={{ width: 100, height: 50 }} />

5.3 响应式布局

javascript 复制代码
import { Dimensions } from 'react-native';

const { width, height } = Dimensions.get('window');

<View style={{ width: width * 0.8 }} />

六、手写简化版 React Native

6.1 核心思路

  1. 解析 JSX 生成虚拟 DOM 2. 遍历虚拟 DOM,生成 Native 指令 3. 通过 Bridge 发送给 Native 4. Native 创建真实 UI

6.2 虚拟 DOM 转指令

javascript 复制代码
function renderToNative(vdom, parentId = 0) {
  const viewId = generateId();
  const instructions = [];

  // 创建视图指令
  instructions.push({
    type: 'createView',
    viewId,
    viewType: vdom.type,  // 'View', 'Text' 等
    parentId,
    props: vdom.props
  });

  // 递归处理子节点
  if (vdom.children) {
    vdom.children.forEach(child => {
      if (typeof child === 'string') {
        // 文本节点
        instructions.push({
          type: 'updateText',
          viewId,
          text: child
        });
      } else {
        instructions.push(...renderToNative(child, viewId));
      }
    });
  }

  return instructions;
}

6.3 Bridge 实现

javascript 复制代码
class Bridge {
  constructor() {
    this.queue = [];
  }

  // JS 调用 Native
  callNative(module, method, args) {
    this.queue.push({ module, method, args });
    this.flush();
  }

  // 批量发送
  flush() {
    if (this.queue.length === 0) return;

    const batch = this.queue.splice(0);
    // 实际会调用 Native 的 C++ 接口
    window.__nativeBridge.processBatch(JSON.stringify(batch));
  }

  // Native 调用 JS
  invokeCallback(callbackId, args) {
    const callback = this.callbacks[callbackId];
    if (callback) callback(...args);
  }
}

6.4 Native 端处理(伪代码)

swift 复制代码
// iOS 端
class NativeBridge {
  func processBatch(_ json: String) {
    let batch = JSON.parse(json)
    
    for instruction in batch {
      switch instruction.type {
      case "createView":
        let view = createView(instruction.viewType)
        view.tag = instruction.viewId
        applyProps(view, instruction.props)
        parentView.addSubview(view)
        
      case "updateText":
        let label = viewRegistry[instruction.viewId] as! UILabel
        label.text = instruction.text
      }
    }
  }
}

6.5 完整示例

javascript 复制代码
// 1. JSX
const App = () => (
  <View style={{ flex: 1 }}>
    <Text>Hello</Text>
  </View>
);

// 2. 转虚拟 DOM
const vdom = {
  type: 'View',
  props: { style: { flex: 1 } },
  children: [
    { type: 'Text', props: {}, children: ['Hello'] }
  ]
};

// 3. 生成指令
const instructions = renderToNative(vdom);
// [
//   { type: 'createView', viewId: 1, viewType: 'View', props: {...} },
//   { type: 'createView', viewId: 2, viewType: 'Text', parentId: 1 },
//   { type: 'updateText', viewId: 2, text: 'Hello' }
// ]

// 4. 发送给 Native
bridge.callNative('UIManager', 'createView', instructions);

七、常用库与生态

7.1 导航

bash 复制代码
npm install @react-navigation/native @react-navigation/stack
javascript 复制代码
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Detail" component={DetailScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

7.2 状态管理

bash 复制代码
npm install zustand
javascript 复制代码
import create from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 }))
}));

function Counter() {
  const { count, increment } = useStore();
  return <Text onPress={increment}>{count}</Text>;
}

7.3 网络请求

javascript 复制代码
fetch('https://api.example.com/data')
  .then(res => res.json())
  .then(data => console.log(data));

// 或使用 axios
import axios from 'axios';
const { data } = await axios.get('/api/data');

八、性能优化

8.1 避免不必要的渲染

javascript 复制代码
import { memo } from 'react';

const ListItem = memo(({ item }) => (
  <Text>{item.name}</Text>
));

8.2 使用 FlatList 而非 ScrollView

javascript 复制代码
// ❌ 差
<ScrollView>
  {data.map(item => <Item key={item.id} />)}
</ScrollView>

// ✅ 好
<FlatList
  data={data}
  renderItem={({ item }) => <Item item={item} />}
/>

8.3 图片优化

javascript 复制代码
<Image
  source={{ uri: url }}
  style={{ width: 200, height: 200 }}
  resizeMode="cover"
  // 启用缓存
  cache="force-cache"
/>

九、调试技巧

9.1 开发者菜单

模拟器中按 Cmd + D(iOS)或 Cmd + M(Android)打开菜单,可以:

  • Reload:重新加载 - Debug:打开 Chrome DevTools - Show Inspector:查看元素

9.2 日志

javascript 复制代码
console.log('普通日志');
console.warn('警告');
console.error('错误');

9.3 Flipper

Facebook 官方调试工具,支持网络、布局、日志等:

bash 复制代码
brew install flipper

十、打包发布

10.1 iOS

bash 复制代码
# 1. 打开 Xcode
open ios/MyApp.xcworkspace

# 2. 选择 Generic iOS Device
# 3. Product -> Archive
# 4. 上传到 App Store Connect

10.2 Android

bash 复制代码
# 1. 生成签名密钥
keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

# 2. 配置 android/gradle.properties
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=***
MYAPP_RELEASE_KEY_PASSWORD=***

# 3. 打包
cd android
./gradlew assembleRelease

# 4. APK 在 android/app/build/outputs/apk/release/

总结

React Native 让你用 JavaScript 写原生应用,核心原理:

  • JS 层运行 React 代码,生成虚拟 DOM - Bridge 传递 JSON 指令给 Native - Native 层创建真实 UI 组件

关键要点:

  • 使用 View、Text、Image 等基础组件 - Flexbox 布局,默认 flexDirection: column - FlatList 处理长列表 - React Navigation 做路由 - 通过 NativeModules 调用原生能力

适合快速开发跨平台应用,性能接近原生。

相关推荐
哇哇哇哇1 小时前
vue3 watch解析
前端
SuperEugene1 小时前
Vite 实战教程:alias/env/proxy 配置 + 打包优化避坑|Vue 工程化必备
前端·javascript·vue.js
兆子龙1 小时前
一文彻底搞懂 OpenClaw 的架构设计与运行原理(万字长文)
javascript
leafyyuki1 小时前
用 AI 和 SDD 重构 Vue2 到 Vue3 的实践记录
前端·人工智能
boooooooom2 小时前
别再用错 ref/reactive!90%程序员踩过的响应式坑,一文根治
javascript·vue.js·面试
德育处主任2 小时前
『NAS』一句话生成网页,在NAS部署UPage
前端·javascript·aigc
前端老兵AI2 小时前
前端工程化实战:Vite + ESLint + Prettier + Husky 从零配置(2026最新版)
前端·vite
bluceli2 小时前
浏览器渲染原理与性能优化实战指南
前端·性能优化
张元清2 小时前
Astro 6.0:被 Cloudflare 收购两个月后,这个"静态框架"要重新定义全栈了
前端·javascript·面试