React Native ✅
React Native 是 Facebook 开发的跨平台移动开发框架, 让开发者可以使用 JavaScript 和 React 构建原生移动应用。 本章涵盖 RN 架构原理、Bridge 通信机制等核心概念。
React Native 工作原理是什么?
答案
核心概念:
React Native 基于三线程架构:JavaScript 线程运行 React 代码, Native UI 线程处理原生渲染,Bridge 负责两者间的异步通信。 通过 Virtual DOM 机制管理 UI 状态变化,最终映射到真实的原生组件上, 实现"Learn once, write anywhere"的跨平台开发体验。
架构组成:
- JavaScript 线程: 执行 React 组件逻辑、状态管理和业务代码
- 原生 UI 线程: 处理真实的原生组件渲染和用户交互
- Bridge 桥接: 序列化消息实现 JS 与原生代码的双向异步通信
- Virtual DOM: React 的虚拟 DOM 机制,高效管理 UI 状态和更新
- 原生组件映射: Text → UILabel/TextView,View → UIView/ViewGroup
示例说明:
Tests
性能特点:
- Bridge 通信是异步的,避免阻塞 UI 线程
- 批量更新减少 Bridge 调用次数,提升性能
- 原生组件直接渲染,获得接近原生应用的体验
- Hot Reload 支持快速开发迭代
面试官视角:
该题考察对 React Native 底层架构的理解:
- 要点清单: 理解三线程架构模型;掌握 Bridge 通信机制; 了解 Virtual DOM 到原生组件的映射;知道 RN 与原生开发的区别
- 加分项: 有 RN 项目开发经验;了解性能优化策略; 知道 Hermes 引擎的作用;熟悉原生模块开发
- 常见失误: 认为 RN 直接编译为原生代码;不理解异步通信的重要性; 混淆 RN 与 WebView 方案;忽视性能考虑
延伸阅读:
- React Native Architecture — 官方架构文档
- The New React Native Architecture — 新架构 Fabric 和 Turbo Modules
- React Native Performance — 官方性能优化指南
动画与手势应如何实现与优化?
答案
核心概念:
动画与手势若由 JS 线程驱动,易受阻塞影响。应尽量使用 原生驱动与工作线程(Reanimated)实现平滑 60fps 体验。
实践要点:
- 动画库:
react-native-reanimated、react-native-animated - 手势库:
react-native-gesture-handler代替 RN 内置手势 - 原生驱动: 复杂动画使用 Reanimated worklets 与 UI 线程执行
- 协调: 手势状态机 + 动画中断/复位策略
示例说明:
// Reanimated v2 基础示例(示意)
import Animated, { useSharedValue, useAnimatedStyle,
withSpring } from 'react-native-reanimated'
const x = useSharedValue(0)
const style = useAnimatedStyle(() => ({ transform: [{ translateX: x.value }] }))
// onPress: x.value = withSpring(100)
面试官视角:
- 要点清单: 原生驱动的必要性;手势与动画配合
- 加分项: 复杂手势场景(列表侧滑/吸附)落地经验
- 常见失误: JS 驱动长链路动画;忽视中断与回弹
延伸阅读:
布局与样式有哪些坑与最佳实践?
答案
核心概念:
RN 使用 Yoga 实现 Flexbox,样式非 CSS 全集;像素密度、 阴影、文本排版与安全区域等需专门适配。
实践要点:
- Flex: 明确轴向、
flexShrink/flexBasis、最小约束 - 尺寸单位: DP 与像素密度;
PixelRatio.get()按需换算 - 阴影与圆角: iOS
shadow*/Androidelevation差异 - 安全区域:
SafeAreaView/react-native-safe-area-context - 文本: 逐行截断、行高、字重在两端差异
示例说明:
import { PixelRatio } from 'react-native'
const hairline = 1 / PixelRatio.get()
面试官视角:
- 要点清单: Yoga 差异点;双端阴影与安全区
- 加分项: 组件库规范化;动态字号/无障碍兼容
- 常见失误: 依赖 Web CSS 心智;忽略多密度适配
延伸阅读:
网络与离线能力如何设计?
答案
核心概念:
移动网络不稳定,需具备重试、缓存、离线队列与冲突解决。
实践要点:
- 请求层: 超时/重试/退避;统一错误码与埋点
- 缓存层: SWR/Stale-While-Revalidate 思路;本地缓存
- 离线: 队列累积 + 网络恢复重放;幂等设计
- 推送同步: 重要数据用推送/轮询刷新
示例说明:
// 退避重试(示意)
for (let i = 0; i < 3; i++) try { return await fetch(url) } catch {}
面试官视角:
- 要点清单: 不稳定网络策略;一致性与幂等
- 加分项: 离线表单/冲突合并经验
- 常见失误: 只做简单失败重试;无监控
延伸阅读:
调试与性能诊断如何落地?
答案
核心概念:
通过 Flipper、Perf Monitor、Systrace/Trace,定位 JS 与 原生瓶颈,量化优化效果。
实践要点:
- Flipper: 网络、布局、崩溃、性能插件
- Profiling: JS CPU profile、堆快照
- Trace: Android Systrace、iOS Instruments
- 指标: 启动、掉帧、内存、交互延迟
示例说明:
// 开启 RN Perf Monitor(开发)
// Dev Menu → Performance Monitor
面试官视角:
- 要点清单: 工具链使用熟练;可量化定位
- 加分项: 建立团队度量看板;基准测试
- 常见失误: 仅凭体验;缺数据支撑
延伸阅读:
本地存储方案如何取舍?
答案
核心概念:
根据性能/安全/结构化需求选择 AsyncStorage、MMKV、 SQLite/Realm/WatermelonDB 等。
实践要点:
- KV: AsyncStorage(通用);MMKV(高性能、C++)
- 结构化: Realm/SQLite/WatermelonDB 同步/索引
- 加密: Keychain/Keystore + 本地加密
示例说明:
import MMKV from 'react-native-mmkv'
const storage = new MMKV(); storage.set('k', 'v')
面试官视角:
- 要点清单: 与业务匹配的选型与迁移
- 加分项: 数据迁移/同步冲突处理
- 常见失误: 大对象塞入 AsyncStorage;未加密
延伸阅读:
错误处理与崩溃治理如何做?
答案
核心概念:
JS 错误与原生崩溃需分别捕获与上报;对用户友好降级。
实践要点:
- JS: Error Boundary、全局未捕获与 Promise rejection
- 原生: 崩溃收集(Sentry/Firebase Crashlytics)
- 回退: 关键功能降级/回滚;CodePush 回滚
示例说明:
// 简化版 Error Boundary
class EB extends React.Component { componentDidCatch(){/*report*/} render(){
return this.props.children }
}
面试官视角:
- 要点清单: 分层收集与隔离;用户可感知的恢复
- 加分项: 回滚链路自动化;错误聚类
- 常见失误: 只上报不回滚;错误打爆日志
延伸阅读:
应用体积如何优化?
答案
核心概念:
体积影响下载转化与冷启动。通过资源压缩、代码瘦身与分割 交付降低包体。
实践要点:
- 资源: WebP/AVIF、按密度打包、移除未用资源
- 代码: Hermes、Proguard/R8、deadcode 移除
- 分发: Android App Bundle,iOS Bitcode(历史)与 Slices
面试官视角:
- 要点清单: 资源/代码/分发三层优化
- 加分项: 量化体积与启动收益
- 常见失误: 资源未清理;多架构全部打入
延伸阅读:
- App Size — 相关分发与签名文档
Monorepo 与多包协作如何落地?
答案
核心概念:
通过 Yarn Workspaces/Turbo/PNPM 管理多包,Metro/Gradle/ Pods 需相应配置。
实践要点:
- Metro:
watchFolders/resolver适配 workspace - Gradle/Pods: 本地依赖/版本对齐/缓存
- 发布: 内部包版本策略与变更日志
示例说明:
// metro.config.js(示意)
module.exports = { watchFolders: [path.resolve(__dirname, '../packages')] }
面试官视角:
- 要点清单: 构建链路完整与稳定性
- 加分项: 复杂依赖树治理;多应用共用组件库
- 常见失误: Metro 未配置导致解析失败
延伸阅读:
推送通知与消息到达如何实现?
答案
核心概念:
推送包含系统通知与应用内消息,需处理权限、到达率与 多厂商通道。
实践要点:
- 服务: FCM/APNs,国内多厂商聚合
- 权限: iOS 权限弹窗策略与引导
- 到达: 前后台/杀进程、离线消息拉取
- 埋点: 展示/点击/转化闭环
面试官视角:
- 要点清单: 权限与到达;国内外通道差异
- 加分项: 富媒体通知与深链联动
- 常见失误: 权限弹窗时机错误;忽视渠道到达差异
延伸阅读:
RN 状态管理如何选择与落地?
答案
核心概念:
RN 可选方案包括 Redux/Toolkit、Recoil、Zustand、MobX, 以及 Context + hooks。选择取决于数据流复杂度、团队经验、 可调试性与生态。
实践要点:
- Redux Toolkit: 规约化、可预测、生态完善、DevTools 友好
- Zustand: 轻量、无样板、选择器减少重渲染
- Recoil: 原子化依赖关系,细粒度更新
- Context: 仅限轻量场景,避免全量重渲染
示例说明:
// Zustand store 示例(避免全量重渲染)
import create from 'zustand'
type State = { count: number; inc: () => void }
export const useCounter = create<State>((set) => ({
count: 0,
inc: () => set((s) => ({ count: s.count + 1 }))
}))
面试官视角:
- 要点清单: 能结合规模/调试/性能做方案权衡
- 加分项: 拆分 selector、避免重渲染的实践经验
- 常见失误: 滥用 Context;缺少持久化与恢复策略
延伸阅读:
图片与资源加载如何优化?
答案
核心概念:
移动端瓶颈在于网络延迟、解码与内存。策略包含缓存、渐进、 占位与尺寸裁剪,必要时采用原生库。
实践要点:
- 缓存:
react-native-fast-image、分辨率按需 - 占位与渐进: 先显示低清,再替换高清
- 内存控制: 控制并发、列表卸载、避免巨大位图
- 预加载: 关键图片/字体启动前预热
示例说明:
// FastImage 渐进占位
import FastImage from 'react-native-fast-image'
<FastImage
source={{ uri: highRes }}
defaultSource={require('./placeholder.png')}
resizeMode={FastImage.resizeMode.cover}
/>
面试官视角:
- 要点清单: 缓存/占位/尺寸/并发的全链路意识
- 加分项: OOM 实战排查;首屏关键资源策略
- 常见失误: 原图直出;在列表中不做回收
延伸阅读:
RN 测试体系如何搭建?
答案
核心概念:
单测(Jest)、组件测试(react-native-testing-library)、 端到端(Detox)。目标是覆盖关键逻辑、可交互流程与回归用例。
实践要点:
- Jest: 纯函数/hooks 单测、网络与时间 mock
- RNTL: 可访问性查询、模拟用户交互
- Detox: 真机/模拟器 E2E、CI 并行稳定性
示例说明:
// RNTL 交互测试示例
import { render, fireEvent } from '@testing-library/react-native'
test('increase counter', () => {
const { getByText } = render(<Counter />)
fireEvent.press(getByText('Plus'))
expect(getByText('1')).toBeTruthy()
})
面试官视角:
- 要点清单: 分层测试策略;Mock 与稳定性
- 加分项: CI 集成 Detox;快照与可访问性检查
- 常见失误: 仅快照;E2E 不稳定无隔离
延伸阅读:
Deep Link 与 Universal Link 如何落地?
答案
核心概念:
通过 URL 触发应用打开并路由到指定页面。iOS 使用 Universal Links,Android 使用 App Links/Intent 过滤器。
实践要点:
- 路由层解析参数并去抖
- Web 与 App 互跳、回跳协议
- 推送/分享/营销链接收口到统一解析
示例说明:
// React Navigation deep link 配置(示意)
const linking = {
prefixes: ['myapp://', 'https://example.com'],
config: { screens: { Profile: 'u/:id' } }
}
面试官视角:
- 要点清单: 配置、解析、容错与安全
- 加分项: H5/App/小程序一体化链接治理
- 常见失误: 未考虑历史回退/多实例
延伸阅读:
权限与后台任务如何处理?
答案
核心概念:
权限请求需遵循平台规范并提供解释文案;后台任务涉及 电量与平台限制,需最小化策略。
实践要点:
- 权限:
react-native-permissions统一封装 - 后台: 背景定位/下载/任务调度按平台限制实现
- 隐私: 收集前告知/最小化、系统设置跳转
示例说明:
import { check, request, PERMISSIONS } from 'react-native-permissions'
await request(PERMISSIONS.IOS.CAMERA)
面试官视角:
- 要点清单: 合规、文案、失败与兜底
- 加分项: 后台策略与降级;异常监控
- 常见失误: 直接拒绝未兜底;过度后台
延伸阅读:
可访问性与国际化如何实践?
答案
核心概念:
可访问性提高可用性与合规;国际化涉及多语言、方向与 本地化格式化。
实践要点:
- A11y:
accessibilityLabel、可聚焦、触达区域、对比度 - I18n:
react-intl/i18next、RTL 支持与动态切换 - 测试: TalkBack/VoiceOver 回归用例
示例说明:
<Button accessibilityLabel="submit order" title="Submit" />
面试官视角:
- 要点清单: A11y 与 I18n 的工程系统化
- 加分项: 可访问性自动化校验;RTL 实战
- 常见失误: 仅文案翻译;忽视语义与读屏
延伸阅读:
安全与数据保护的最佳实践?
答案
核心概念:
移动端安全关注数据存储、传输与运行环境。RN 需结合 原生能力与后端配合。
实践要点:
- 存储: Keychain/Keystore、安全区、避免明文
- 网络: TLS pinning、超时与重试、请求签名
- 环境: 越狱/Root 检测、调试开关、代码混淆
- 日志: 不打敏感数据;崩溃与性能上报脱敏
面试官视角:
- 要点清单: 端到端的威胁建模;最小化原则
- 加分项: Pinning 与签名落地;反调试经验
- 常见失误: Token 落地明文;日志泄露
延伸阅读:
CI/CD 与构建交付如何设计?
答案
核心概念:
统一版本、自动化打包签名、静态检查、测试与发布流程, 兼顾多环境与多渠道。
实践要点:
- 管道: Lint/TypeCheck → 单测 → 构建 → E2E → 发布
- 缓存: Metro/Gradle/CocoaPods 缓存
- 密钥: 安全存放、短有效期、最小权限
- Release: 灰度、回滚与符号表管理
面试官视角:
- 要点清单: 稳定、可重复与可观测
- 加分项: 多仓/Monorepo;差异化构建
- 常见失误: 缓存不当导致非确定性;密钥泄漏
延伸阅读:
RN 的跨平台能力与局限是什么?
答案
核心概念:
React Native 通过 JS 运行时 + Bridge 将同一套业务逻辑复用到 iOS/Android。UI 层使用原生控件渲染,性能接近原生。跨平台并非 “一次编写到处运行”,平台差异与生态差异仍需工程化治理。
能力与边界:
- 可共享: 业务逻辑、状态管理、网络、数据层、通用组件库
- 平台差异: 权限体系、导航栈、手势、输入法、文件系统
- UI 差异: 字体排版、阴影、滚动弹性、系统样式与动态颜色
- 硬件能力: 相机蓝牙 NFC 等需依赖原生模块,兼容性各异
- 生态差异: 三方库维护水平不一,需评估稳定性与安全性
示例说明:
// 简单的跨平台分支与样式适配示例
import { Platform } from 'react-native'
export const isIOS = Platform.OS === 'ios'
export const Touchable = isIOS
? require('react-native').TouchableOpacity
: require('react-native-gesture-handler').TouchableOpacity
面试官视角:
该题检验对跨平台“边界”的认知与工程取舍。
- 要点清单: 明确共享与不可共享的层次;能举出典型差异; 说明适配策略与测试策略
- 加分项: 形成可复用的适配封装;多包体多渠道交付经验; 端能力降级与兜底策略
- 常见失误: 认为 100% 共享;忽视输入法、权限、布局差异; 滥用三方库不做评估
延伸阅读:
- Platform Specific Code — 官方平台差异指南
新架构 Fabric / TurboModule 与旧架构对比?
答案
核心概念:
新架构以 JSI 为基础,取消传统异步字符串序列化的 Bridge, 引入 Fabric 渲染管线与 TurboModule 原生模块系统, 实现更快的同步/异步交互与更低开销。
对比要点:
- 通信: 旧 Bridge(JSON 串) → JSI(直接对象/函数)
- 渲染: UIManager → Fabric(更细粒度、并发友好)
- 模块: NativeModule → TurboModule(Codegen、类型安全)
- 性能: 启动更快、交互延迟更低、内存占用更小
- 迁移: 打开新架构开关、升级库、按需改造自定义模块
示例说明:
// TurboModule 类型定义 (示意)
export interface Spec {
getDeviceName(): Promise<string>
}
面试官视角:
- 要点清单: 说清 JSI/Fabric/TurboModule 的关系; 性能收益点;迁移风险点
- 加分项: 有新架构落地经验;能解释 Codegen 流程与类型安全
- 常见失误: 把 JSI 等同“全部同步”;忽视三方库兼容性
延伸阅读:
- New Architecture — 官方新架构入口
RN 性能优化实战有哪些?
答案
核心概念:
性能瓶颈常见于渲染频繁、列表场景、手势动画与启动链路。 原则是“减少渲染、低成本通信、原生驱动动画、按需加载”。
优化清单:
- 重渲染控制:
memo、useCallback、useMemo、 分离 Context 消费边界 - 列表:
FlatList/SectionList合理getItemLayout、windowSize、removeClippedSubviews - 动画:
react-native-reanimated、useNativeDriver: true - 交互:
react-native-gesture-handler降低 JS 线程压力 - 通信: 合并批量更新,减少桥消息数
- 启动: 减少 JS 体积、启用 Hermes、延迟非关键初始化
示例说明:
// 控制重渲染示例
const Row = React.memo(({ item }: { item: Item }) => {
return <ItemCell item={item} />
})
面试官视角:
- 要点清单: 能从“渲染、动画、通信、启动”四维度给出方案
- 加分项: 现场定位与量化(Perf Monitor、Flipper、Systrace)
- 常见失误: 一味乐观更新;忽视长列表窗口化与键盘交互
延伸阅读:
- Performance — 官方性能指南
如何编写原生模块与原生 UI 组件?
答案
核心概念:
通过模块化接口把原生能力暴露给 JS 层。旧架构使用 NativeModule, 新架构推荐 TurboModule/Codegen, UI 层使用 Fabric 组件。
实现流程:
- 定义接口: TypeScript/Flow 声明(供 Codegen)
- 平台实现: iOS(ObjC/Swift),Android(Java/Kotlin)
- 注册导出: 模块/视图管理器注册,导出到 JS
- 测试发布: 示例 App 自测、E2E、版本策略
示例说明:
// JS 声明 (示意)
export interface DeviceSpec { getBatteryLevel(): Promise<number> }
面试官视角:
- 要点清单: 清楚工程化流程与差异点;理解 Codegen 与类型边界
- 加分项: 拥有跨端模块模板脚手架;发布多版本兼容
- 常见失误: 同步 API 滥用;线程/生命周期处理不当
延伸阅读:
- Native Modules — 官方原生模块指南
导航方案如何选择与取舍?
答案
核心概念:
主流为 React Navigation(JS 驱动) 与 react-native-navigation(Wix,原生驱动)。选择取决于性能、 可扩展与团队经验。
对比要点:
| 方案 | 驱动 | 性能 | 动画 | 生态 |
|---|---|---|---|---|
| React Navigation | JS | 中 | Reanimated | 丰富 |
| RNN(Wix) | 原生 | 高 | 原生 | 偏少 |
面试官视角:
- 要点清单: 能结合业务体量、转场复杂度给出选择理由
- 加分项: 自定义转场/手势方案;Deep Link 与权限路由
- 常见失误: 路由结构混乱、状态泄漏、硬返回冲突
延伸阅读:
打包发布与 OTA 有哪些要点?
答案
核心概念:
移动端交付涉及签名、打包变体、灰度与 OTA(CodePush)。需兼顾 商店合规与风险控制。
实践要点:
- 签名与证书: iOS Profile/证书、Android keystore
- 多环境/多渠道: scheme/flavor 管理配置
- Hermes: 体积与启动收益评估
- CodePush/OTA: 与商店条款、敏感变更边界
- 可观测性: 崩溃/性能/业务指标(Flipper、Sentry、Apm)
面试官视角:
- 要点清单: 交付流程清晰;能阐述 OTA 合规与回滚策略
- 加分项: 自动化流水线、符号表管理、灰度策略
- 常见失误: OTA 越权更新、密钥泄漏、渠道包混乱
延伸阅读:
Hermes 引擎的价值与限制是什么?
答案
核心概念:
Hermes 是面向 RN 的轻量 JS 引擎,支持预编译字节码、快速 启动、较低内存占用。但与 V8/JSCore 存在内建特性差异, 需留意三方依赖兼容性。
收益与权衡:
- 启动: 字节码快启,减少解析时间
- 内存: 小型设备更友好
- 体积: 引擎体积 + 应用字节码总体需评估
- 兼容: Intl/Proxy 等特性支持差异需验证
面试官视角:
- 要点清单: 描述启动与内存收益;能给出不适用场景
- 加分项: 线上切换评估数据;字节码缓存与多包体策略
- 常见失误: 忽视 polyfill/Intl;误判对动画库的影响
延伸阅读:
JSBridge 是什么?原理是什么?
答案
核心概念:
JSBridge 是连接 JavaScript 和原生代码的通信桥梁, 在混合应用开发中实现 WebView 与原生功能的双向调用。 通过消息序列化、回调管理和异步队列机制, 让 Web 技术能够访问设备原生能力如相机、存储、定位等, 同时保持良好的性能和安全性。
通信机制:
- JS → Native: JavaScript 通过注入对象或 URL Schema 调用原生方法
- Native → JS: 原生代码通过 evaluateJavaScript 执行 WebView 中的 JS 函数
- 消息序列化: JSON 格式传递复杂数据结构和参数
- 回调管理: 使用唯一 ID 管理异步回调,确保结果正确返回
- 错误处理: 完善的异常捕获和错误回调机制
示例说明:
Tests
实现方式对比:
| 平台 | 实现方式 | 优点 | 缺点 |
|---|---|---|---|
| iOS | WKWebView + MessageHandler | 性能好,安全性高 | iOS 8+ 支持 |
| Android | WebView + JavascriptInterface | 兼容性好 | 安全风险需注意 |
| 统一方案 | PostMessage + URL Schema | 跨平台一致 | 复杂度较高 |
安全考虑:
- 输入验证: 严格验证来自 JS 的调用参数
- 方法白名单: 只暴露必要的原生接口给 WebView
- 权限控制: 敏感操作需要用户授权确认
- 数据加密: 传输敏感信息时进行加密处理
面试官视角:
该题考察混合开发和跨平台通信的理解:
- 要点清单: 理解 JSBridge 通信原理;掌握双向调用机制; 了解异步回调处理;知道安全性考虑
- 加分项: 有混合应用开发经验;了解不同平台的实现差异; 知道性能优化方法;熟悉相关安全问题
- 常见失误: 忽视异步特性导致的问题;不考虑安全性风险; 不理解回调管理的复杂性;混淆不同的实现方案
延伸阅读:
- WKWebView MessageHandler — iOS WebView 通信官方文档
- Android WebView JavascriptInterface — Android WebView 集成指南
- Hybrid App Security — OWASP 移动应用安全指南