01 React Native 基础、核心组件与布局体系

React Native 不是"把 HTML 写进手机"。它使用 React 的组件模型和状态模型,但渲染目标是 Android 和 iOS 的原生视图。学习 React Native 的第一步,是把 Web 心智切换到移动端心智:没有 DOM、没有 CSS 完整层叠模型、没有浏览器布局默认行为,只有平台视图、触摸交互、设备尺寸、原生能力和跨平台差异。

1. React Native 解决什么问题

React Native 让你用 JavaScript 和 React 描述移动应用 UI,同时运行时创建 Android / iOS 原生视图。

text 复制代码
React Component -> React Native Renderer -> Native View

例如:

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

export default function App() {
  return (
    <View>
      <Text>Hello React Native</Text>
    </View>
  );
}

View 不是 divText 不是 p。它们最终映射到平台原生控件。

2. 与 React Web 的关键差异

维度 React Web React Native
渲染目标 DOM Android/iOS 原生视图
文本 任意标签内可放文本 文本必须放在 Text
样式 CSS、class、层叠 JS 对象、StyleSheet、有限 CSS 子集
布局 block、inline、flex、grid 默认 Flexbox,主轴默认 column
事件 鼠标、键盘、浏览器事件 touch、press、gesture、平台事件
导航 URL / Router Stack、Tabs、Deep Link
资源 浏览器加载 Metro bundler、原生资源
平台能力 Web API Native Module、Expo API、平台 SDK

3. 核心组件地图

React Native 官方核心组件可按场景理解:

基础组件:

  • View:容器,类似非滚动布局块。
  • Text:文本展示。
  • Image:图片。
  • TextInput:输入框。
  • Pressable:触摸交互容器。
  • ScrollView:滚动容器。
  • StyleSheet:样式声明。

界面组件:

  • Button:基础按钮。
  • Switch:布尔开关。
  • ActivityIndicator:加载指示器。
  • Modal:模态层。
  • Alert:系统弹窗。
  • StatusBar:状态栏控制。

列表:

  • FlatList:高性能列表。
  • SectionList:分组列表。
  • VirtualizedList:底层虚拟列表。

设备和平台:

  • Dimensions:屏幕尺寸。
  • PixelRatio:像素密度。
  • KeyboardAvoidingView:键盘避让。
  • Linking:链接和 Deep Link。
  • BackHandler:Android 返回键。
  • PermissionsAndroid:Android 权限。
  • ActionSheetIOS:iOS Action Sheet。
  • ToastAndroid:Android Toast。

4. View

View 是最基础的容器。

jsx 复制代码
function Card({ children }) {
  return <View style={styles.card}>{children}</View>;
}

const styles = StyleSheet.create({
  card: {
    padding: 16,
    borderRadius: 12,
    backgroundColor: '#FFFFFF',
  },
});

注意:

  • View 不能直接放字符串。
  • 触摸交互优先用 Pressable
  • 阴影、边框、圆角在 Android/iOS 上表现不同。

5. Text

文本必须放在 Text 中。

jsx 复制代码
function Title({ children }) {
  return <Text style={styles.title}>{children}</Text>;
}

嵌套文本:

jsx 复制代码
<Text>
  React Native <Text style={styles.emphasis}>移动端体系</Text>
</Text>

常见属性:

  • numberOfLines
  • ellipsizeMode
  • selectable
  • allowFontScaling
  • onPress
jsx 复制代码
<Text numberOfLines={2} ellipsizeMode="tail">
  一段很长的课程简介...
</Text>

6. Image

本地图片:

jsx 复制代码
<Image source={require('./assets/logo.png')} style={styles.logo} />

远程图片:

jsx 复制代码
<Image
  source={{ uri: 'https://example.com/avatar.png' }}
  style={styles.avatar}
/>

必须给明确尺寸:

jsx 复制代码
const styles = StyleSheet.create({
  avatar: {
    width: 48,
    height: 48,
    borderRadius: 24,
  },
});

移动端图片要关注:

  • 分辨率和像素密度。
  • 缓存策略。
  • 占位图。
  • 失败状态。
  • 大图内存。

7. Pressable

Pressable 是现代触摸交互基础组件。

jsx 复制代码
function PrimaryButton({ children, onPress }) {
  return (
    <Pressable
      onPress={onPress}
      style={({ pressed }) => [
        styles.button,
        pressed && styles.buttonPressed,
      ]}
    >
      <Text style={styles.buttonText}>{children}</Text>
    </Pressable>
  );
}

相比 TouchableOpacityPressable 能表达更多交互阶段:

  • pressed
  • hovered
  • focused

8. TextInput

jsx 复制代码
function SearchInput({ value, onChangeText }) {
  return (
    <TextInput
      value={value}
      onChangeText={onChangeText}
      placeholder="搜索知识点"
      returnKeyType="search"
      style={styles.input}
    />
  );
}

常用属性:

  • value
  • onChangeText
  • placeholder
  • keyboardType
  • secureTextEntry
  • returnKeyType
  • autoCapitalize
  • multiline

移动端表单必须考虑键盘遮挡、输入法、自动大写、密码安全和提交按钮。

9. ScrollView

ScrollView 会一次性渲染所有子元素。

jsx 复制代码
<ScrollView contentContainerStyle={styles.content}>
  {items.map((item) => (
    <KnowledgeCard key={item.id} item={item} />
  ))}
</ScrollView>

适合:

  • 内容较少。
  • 静态页面。
  • 表单页。

不适合:

  • 长列表。
  • 无限滚动。
  • 数据量不可控列表。

长列表优先使用 FlatList

10. FlatList

jsx 复制代码
<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => <KnowledgeCard item={item} />}
/>

常用优化:

jsx 复制代码
<FlatList
  data={items}
  keyExtractor={(item) => item.id}
  renderItem={renderItem}
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={7}
  removeClippedSubviews
/>

专家提醒:

  • renderItem 尽量稳定。
  • keyExtractor 必须稳定。
  • 行高固定时使用 getItemLayout
  • 大列表避免内联匿名组件和复杂阴影。

11. SectionList

适合分组列表。

jsx 复制代码
<SectionList
  sections={[
    { title: '入门', data: beginnerItems },
    { title: '进阶', data: advancedItems },
  ]}
  keyExtractor={(item) => item.id}
  renderItem={({ item }) => <KnowledgeCard item={item} />}
  renderSectionHeader={({ section }) => (
    <Text style={styles.sectionTitle}>{section.title}</Text>
  )}
/>

12. StyleSheet

jsx 复制代码
const styles = StyleSheet.create({
  screen: {
    flex: 1,
    backgroundColor: '#F4F7F8',
    padding: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: '700',
    color: '#172026',
  },
});

React Native 样式是 JS 对象,不是 CSS:

  • 使用 camelCase。
  • 数字通常表示 dp。
  • 没有完整 CSS 选择器。
  • 没有继承式 className。
  • 默认主轴是 column。

13. Flexbox 布局

React Native 默认:

text 复制代码
flexDirection: 'column'

常见布局:

jsx 复制代码
const styles = StyleSheet.create({
  row: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    gap: 12,
  },
});

占满屏幕:

jsx 复制代码
screen: {
  flex: 1,
}

移动端布局要考虑:

  • 小屏幕。
  • 横竖屏。
  • 刘海屏。
  • 字体缩放。
  • Android/iOS 默认差异。

14. Safe Area

iPhone 刘海、动态岛、Android 状态栏都可能遮挡内容。

Expo / community 常用:

jsx 复制代码
import { SafeAreaView } from 'react-native-safe-area-context';

function Screen() {
  return (
    <SafeAreaView style={{ flex: 1 }}>
      <Content />
    </SafeAreaView>
  );
}

基础 RN 也有 SafeAreaView,但实际项目更常使用 react-native-safe-area-context

15. Platform

平台差异:

jsx 复制代码
import { Platform } from 'react-native';

const styles = StyleSheet.create({
  card: {
    padding: 16,
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOpacity: 0.12,
        shadowRadius: 8,
      },
      android: {
        elevation: 3,
      },
    }),
  },
});

文件级差异:

text 复制代码
Button.ios.tsx
Button.android.tsx

16. Dimensions 与响应式

jsx 复制代码
const { width } = useWindowDimensions();

const columns = width > 700 ? 2 : 1;

不要只按机型判断。移动端响应式要结合:

  • 屏幕宽度。
  • 横竖屏。
  • 字体缩放。
  • 平板。
  • 分屏模式。

17. PixelRatio

jsx 复制代码
const hairlineWidth = StyleSheet.hairlineWidth;

图片资源要考虑不同像素密度:

text 复制代码
icon.png
icon@2x.png
icon@3x.png

18. 基础 Demo

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

export function ComponentBasicsDemo() {
  const [count, setCount] = React.useState(0);

  return (
    <View style={styles.card}>
      <Text style={styles.title}>React Native 基础</Text>
      <Text style={styles.summary}>View、Text、Pressable 与 StyleSheet。</Text>
      <Pressable style={styles.button} onPress={() => setCount(count + 1)}>
        <Text style={styles.buttonText}>点击 {count}</Text>
      </Pressable>
    </View>
  );
}

19. 入门达标标准

你应该能独立完成:

  • ViewTextImagePressable 组成页面。
  • StyleSheet 写清晰样式。
  • 用 Flexbox 做移动端布局。
  • 正确处理文本、图片、输入框和滚动容器。
  • 知道什么时候用 ScrollView,什么时候用 FlatList
  • 处理基础平台差异和 Safe Area。

20. 核心组件扩展清单

ViewTextImageTextInputPressable 是最小基础,但真实项目还会高频使用:

  • ActivityIndicator:局部 loading。
  • Modal:全屏或局部弹层。
  • Alert:系统确认弹窗。
  • Switch:布尔配置。
  • StatusBar:状态栏颜色和内容模式。
  • KeyboardAvoidingView:键盘遮挡处理。
  • RefreshControl:下拉刷新。

Modal 示例:

jsx 复制代码
<Modal visible={open} animationType="slide" onRequestClose={close}>
  <View style={styles.modal}>
    <Text style={styles.title}>确认删除</Text>
    <Pressable onPress={close}>
      <Text>关闭</Text>
    </Pressable>
  </View>
</Modal>

Android 必须处理 onRequestClose

21. 样式差异扩展

React Native 样式不是 CSS。常见差异:

  • 没有 CSS selector。
  • 没有 cascade。
  • 默认单位是 dp,不写 px。
  • zIndex 在 Android/iOS 上和 Web 不完全一致。
  • 阴影平台差异明显。
  • gap 需要确认 RN 版本支持。
  • 字体族需要平台配置。

阴影跨平台:

jsx 复制代码
const shadow = Platform.select({
  ios: {
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.12,
    shadowRadius: 10,
  },
  android: {
    elevation: 4,
  },
});

22. 移动端布局边界

移动端布局要额外考虑:

  • 小屏设备。
  • 大屏平板。
  • 横屏。
  • 分屏。
  • 字体缩放。
  • 刘海和状态栏。
  • 底部手势条。
  • 键盘弹出。

响应式示例:

jsx 复制代码
function useColumns() {
  const { width } = useWindowDimensions();
  if (width >= 900) return 3;
  if (width >= 600) return 2;
  return 1;
}

23. Text 深水区

移动端文本不是简单字号:

  • allowFontScaling 影响可访问性。
  • Android 字体行高和 iOS 不同。
  • 自定义字体需要原生资源配置。
  • 多语言会让文本长度变化。
  • numberOfLines 需要配合布局宽度。
jsx 复制代码
<Text
  maxFontSizeMultiplier={1.4}
  numberOfLines={2}
  accessibilityRole="header"
>
  React Native 知识体系
</Text>

24. Image 深水区

图片必须关注内存:

  • 列表中不要加载原图。
  • 使用缩略图。
  • 明确 width/height。
  • 处理失败状态。
  • 重要图片可预加载。
  • 头像和封面要区分缓存策略。

图片错误:

jsx 复制代码
<Image source={{ uri }} style={{ flex: 1 }} />

没有明确高度时可能不显示或布局异常。

25. 入门阶段反模式

  • View 里直接写字符串。
  • ScrollView 渲染几百条数据。
  • 图片不设置尺寸。
  • 点击区域太小。
  • 不处理 Safe Area。
  • Web CSS 心智照搬到 RN。
  • 忽略 Android/iOS 样式差异。
  • 表单页不处理键盘遮挡。

26. 基础评审题

  • 文本是否都放在 Text 中?
  • 长列表是否使用 FlatList
  • 图片是否有明确尺寸?
  • 点击目标是否足够大?
  • 是否适配 Safe Area?
  • 是否考虑字体缩放?
  • 是否有平台差异代码?
  • 样式是否使用 theme token?

27. React Native 基础知识点索引

  1. View 是基础容器。
  2. Text 承载所有文本。
  3. Image 必须有尺寸。
  4. TextInput 使用 onChangeText
  5. Pressable 是现代触摸基础。
  6. ScrollView 一次性渲染子元素。
  7. FlatList 适合长列表。
  8. SectionList 适合分组。
  9. StyleSheet 是样式对象。
  10. 默认 flexDirection 是 column。
  11. Safe Area 必须考虑。
  12. 状态栏和底部手势条会遮挡内容。
  13. Android/iOS 阴影不同。
  14. Android 返回键需要处理。
  15. 字体缩放影响布局。
  16. 点击区域要足够大。
  17. 平台差异可用 Platform.select
  18. 图片资源要考虑 @2x/@3x。
  19. 键盘会影响表单布局。
  20. 无障碍不是可选项。

28. 基础练习扩展

  • 实现一个课程卡片。
  • 实现一个搜索输入框。
  • 实现一个分组列表。
  • 实现一个 Modal。
  • 实现一个可访问按钮。
  • 实现一个响应式两列布局。
  • 实现一个键盘避让表单。
  • 实现 iOS/Android 阴影差异。

面试题完整答案总集:React Native 基础、组件与布局

文本是否都放在 Text 中?

React Native 中字符串不能直接放在 View 里,必须放在 Text 中。原因是 React Native 渲染目标是原生视图,文本节点需要映射到平台文本组件。直接把字符串放进 View 会报错或表现异常。

长列表是否应该使用 FlatList?

是。ScrollView 会一次性渲染所有子元素,数据量大时会造成内存和渲染压力。FlatList 基于虚拟化,只渲染可视窗口附近的内容,适合长列表、分页、无限滚动和下拉刷新。

图片为什么必须有明确尺寸?

React Native 没有浏览器图片自动占位布局逻辑。远程图片如果没有 width/height,可能无法正确显示或导致布局抖动。明确尺寸还能降低布局计算成本,并帮助控制内存。

点击目标为什么要足够大?

移动端是手指触摸,不是鼠标精确点击。点击区域过小会导致误触和可访问性问题。通常按钮和图标应使用足够 padding 或 hitSlop 扩大触摸区域。

为什么必须适配 Safe Area?

iPhone 刘海、动态岛、Android 状态栏和底部手势条都可能遮挡内容。Safe Area 能保证内容不被系统区域覆盖,尤其是顶部导航、底部按钮和全屏页面。

字体缩放为什么会影响布局?

用户可能在系统中开启大字体。若布局高度固定或文本容器太窄,字体缩放会导致文字截断、按钮溢出或布局重叠。关键文本应允许合理缩放,并用弹性布局承载。

如何处理 Android/iOS 样式差异?

Platform.select 或平台文件区分。典型差异包括阴影、字体、状态栏、返回键、Modal 行为和某些组件默认样式。跨平台组件应把差异封装在基础组件或 theme 中。

为什么样式要使用 theme token?

theme token 能统一颜色、间距、字号、圆角和阴影,避免页面各写各的。它让设计调整、暗色模式、品牌换肤和组件库治理更容易,也能减少视觉不一致。

相关推荐
空中海1 小时前
05 React架构设计、项目实践与专家清单
前端·react.js·前端框架
前端之虎陈随易3 小时前
2年没用Nodejs了,Bun很香
linux·前端·javascript·vue.js·typescript
空中海4 小时前
04 工程化、质量体系与 React 生态
前端·ubuntu·react.js
Yue1684 小时前
一文教你五分钟学会Zustand,React状态管理更加方便!
react native
空中海4 小时前
03 性能、动画与 React Native 新架构
react native·react.js·架构
好运的阿财5 小时前
OpenClaw工具拆解之host_workspace_write+host_workspace_edit
前端·javascript·人工智能·机器学习·ai编程·openclaw·openclaw工具
XiYang-DING5 小时前
JavaScript
开发语言·javascript·ecmascript
空中海6 小时前
02 React Native状态、导航、数据流与设备能力
javascript·react native·react.js
空中海6 小时前
02 状态、Hooks、副作用与数据流
开发语言·javascript·ecmascript