1.RN基础概念
React Native 是由 Facebook 开发的开源框架,用于构建 iOS 和 Android 应用。它使用 JavaScript 和 React 的核心概念,如组件化和虚拟 DOM,来生成原生 UI 组件。
优势:
- 跨平台开发: 同一代码库可用于 iOS 和 Android。
- 高效的性能: 使用原生组件,性能接近原生应用。
- 快速的开发周期: 热重载功能加快开发和调试速度。
- 丰富的社区支持: 有大量的第三方库和插件可用。
2.如何处理RN的性能问题?
基础概念:
性能问题通常涉及渲染速度慢、内存泄漏或不必要的重新渲染。
解决方法:
- 使用 PureComponent 或 React.memo: 自动进行浅比较,避免不必要的渲染。
- 避免深层次的嵌套组件: 使用 FlatList 或 SectionList 优化长列表。
- 合理使用 shouldComponentUpdate: 手动控制组件的更新逻辑。
- 使用性能监控工具: 如 React Native 的 Performance Monitor。
import React, { memo } from 'react';
const MyComponent = memo((props) => {
return <View><Text>{props.text}</Text></View>;
}, (prevProps, nextProps) => {
return prevProps.text === nextProps.text;
});
3.RN中如何进行网络请求?
React Native 提供了多种方式进行网络请求,常用的包括 Fetch API 和第三方库如 Axios。
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
4.如何解决 React Native 中的内存泄漏问题?
内存泄漏通常是由于未正确清理定时器、事件监听器或其他资源导致的。
解决方法:
1、及时清理定时器和事件监听器: 在 componentWillUnmount 中进行清理。
2、使用弱引用: 避免长时间持有对组件的引用。
class MyComponent extends React.Component {
componentDidMount() {
this.timer = setInterval(() => {
console.log('Timer tick');
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
return <View><Text>My Component</Text></View>;
}
}
5.RN 与 React 的全面对比
一、核心定位差异
| 维度 | React (React.js) | React Native |
|---|---|---|
| 目标平台 | Web 应用开发 | 移动端应用开发 (iOS/Android) |
| 输出产物 | HTML/CSS/JS 网页 | 原生移动应用 |
| 渲染方式 | 虚拟DOM → 浏览器DOM | JS组件 → 原生UI组件 |
二、技术架构对比
- 渲染引擎
- React:使用 ReactDOM 渲染器,输出标准Web元素
- React Native:通过 原生桥接层 将JS组件映射为平台原生组件:
- iOS: 转为 Objective-C/Swift 视图
- Android: 转为 Java/Kotlin 视图
- 线程模型
- React:单线程运行(主线程处理UI和JS)
- React Native:多线程架构:
- JS线程:执行业务逻辑
- 原生线程:处理UI渲染
- Shadow线程:计算布局(Yoga引擎)
三、开发体验差异
- 样式系统
| 特性 | React | React Native |
|---|---|---|
| 样式单位 | px/em/rem/vw等 | 无单位数字(设备无关像素) |
| 布局系统 | CSS Flexbox/Grid | JavaScript Flexbox (Yoga实现) |
| 样式写法 | CSS/Sass或CSS-in-JS | StyleSheet.create() |
| 选择器 | 支持class/id等复杂选择器 | 仅支持简单样式对象 |
// React
<div style={{ padding: '1rem' }} className="container" />
// React Native
<View style={{ padding: 16 }} />
- 导航系统
- React:基于URL路由 (React Router)
- React Native:原生导航栈解决方案:
- React Navigation (主流JS方案)
- React Native Navigation (封装原生导航)
四、性能特征对比
| 指标 | React | React Native |
|---|---|---|
| 启动速度 | 快(纯JS解析) | 较慢(需要初始化桥接) |
| 渲染性能 | 依赖浏览器优化 | 接近原生性能 |
| 动画流畅度 | 依赖CSS/JS动画 | 推荐使用原生驱动动画(Animated API) |
| 内存占用 | 中等 | 较高(维护JS与原生通信) |
五、生态系统对比
- 依赖管理
- React:直接使用npm/webpack生态
- React Native:需要处理原生依赖:
- 原生模块链接 (react-native link)
- CocoaPods (iOS) / Gradle (Android)
- 调试工具
- React:Chrome DevTools + React DevTools
- React Native:
- 专用调试器 (React Native Debugger)
- Flipper (高级调试)
- 需要Xcode/Android Studio调试原生层
6.RN底层原理
React Native让JS代码通过Bridge与原生平台通信,最终渲染成真正的原生组件,而不是WebView。
6-1、核心机制
React Native的核心是Bridge通信机制。JS线程和原生线程通过异步JSON消息通信,JS负责业务逻辑和虚拟DOM,原生层负责渲染真实UI。新版用JSI替代Bridge,支持同步调用,性能大幅提升。
6-2、渲染流程
渲染流程分三步:JS层创建虚拟树 → Bridge传递布局信息 → 原生层用Yoga引擎计算并渲染。
Yoga是Facebook的Flexbox布局引擎,保证跨平台一致性。新架构Fabric实现了同步渲染,解决了异步带来的卡顿问题。
和Flutter的区别
React Native是JS+原生渲染,Flutter是Dart+自绘引擎。RN更接近原生体验,Flutter更统一但包体更大。
7.RN与原生通信
RN通过Bridge在JavaScript和原生代码间建立异步通信,调用相册就是JS通过Bridge调用原生模块,原生执行后通过Callback/Promise将结果返回给JS。
7-1、通信流程
1、JS调用NativeModule方法
2、Bridge序列化为JSON消息 {module:'CameraRoll',method:'getPhotos'}
3、Native解析消息,执行原生代码 iOS: UIImagePickerController,Android: Intent.ACTION_PICK
4、原生结果通过Callback/Promise返回
5、JS处理返回结果,更新UI
// Bridge工作流程
JS Thread → Bridge → Native Thread
↓ ↓ ↓
JS代码 JSON序列化 原生执行
消息队列 方法调用
- Bridge特点:
- 异步通信(有延迟)
- JSON序列化(有性能开销)
- 单线程JS执行(可能阻塞)
JSI层(新架构改进)
// JSI (JavaScript Interface) 新架构
JS Thread → 直接调用C++对象 → Native Thread
↓ ↓ ↓
JS代码 同步调用 原生执行
无序列化 方法调用
- JSI优势:
- 同步调用(更快)
- 类型安全
- 内存共享
7-2、调用相册功能完整流程
阶段1:JavaScript端调用
// 1. 导入NativeModules
import { NativeModules } from 'react-native';
// 2. 获取原生模块
const { ImagePicker } = NativeModules;
// 3. 调用原生方法
async function pickImage() {
try {
// 调用原生模块的pickImage方法
const result = await ImagePicker.pickImage({
mediaType: 'photo', // 选择照片
allowsEditing: true, // 允许编辑
quality: 0.8 // 图片质量
});
console.log('选择的图片:', result);
return result.uri;
} catch (error) {
console.error('选择图片失败:', error);
}
}
// 4. 在组件中使用
function PhotoPicker() {
const [imageUri, setImageUri] = useState(null);
const handlePickImage = async () => {
const uri = await pickImage();
if (uri) {
setImageUri(uri);
}
};
return (
<View>
<Button title="选择照片" onPress={handlePickImage} />
{imageUri && <Image source={{ uri: imageUri }} />}
</View>
);
}
阶段2:Bridge通信细节
// 实际Bridge通信过程
const message = {
module: 'ImagePicker', // 模块名
method: 'pickImage', // 方法名
args: [{ // 参数
mediaType: 'photo',
allowsEditing: true,
quality: 0.8
}],
callbackId: 12345 // 回调ID
};
// Bridge将消息序列化为JSON
const jsonMessage = JSON.stringify(message);
// 通过MessageQueue发送到Native
// MessageQueue是RN内部的消息队列
__fbBatchedBridge.callFunctionReturnFlushedQueue(
'ImagePicker',
'pickImage',
[{
mediaType: 'photo',
allowsEditing: true,
quality: 0.8
}]
);
阶段3:原生实现
其他项目问题
o1.RN填充父元素高度
flex: 1
render() {
return (
<View style={{ flex: 1 }}></View>
)
}
o2.Text组件必须用Text组件包裹
right:
{roomName ? <Text>|</Text> : null}
error:
{roomName && <Text>|</Text>}
o3.TextInput组件,输入完成,没有失去焦点的解决方法
<TextInput
blurOnSubmit={true}
/>
