太无聊了最近,找点事做,学一下RN丰富一下技术栈🫡。但是开发APP除了RN,还有一种选择就是WebView,但是基于WebView的APP的性能被普遍认为不如RN,因为WebView本质上是一个容器,用于在应用中嵌入网页或 HTML,它最主要的工作是将Web内容(HTML、CSS和JS)渲染到应用中。基于WebView的APP就像“在手机里又下载了一个浏览器,这是这个‘浏览器’专门用来呈现这个APP的内容”?像通过uni-app开发的APP就是默认基于WebView技术的。
而RN是一个混合框架,它通过桥接将JS和原生代码(如iOS的Objective-C或Swift,Android的Java或Kotlin)连接起来,我们可以使用React来编写UI和交互,而一些性能要求较高的部分(如摄像头、加速计等)则可以通过原生模块来处理。
RN的桥接我觉得很像Electron,Electron最猛的就是“可以调用Node环境下的API,再通过进程间的通信把调用结果传递到渲染进程(UI界面)。而Node那些API干的活便是调用操作系统提供的接口 (如果我没记错的话)”,这种做法带来的作用就是开发者“仿佛可以在浏览器环境下调用操作系统原生的功能”,也算得上一种“桥接”吧。但Electron在渲染进程里干的事又很像WebView,因为他的UI是跑在浏览器环境下的,之前在zhihu上看到过一老哥说的一句话贼经典:一想到一下载一个Electron应用,我的电脑里就多了一个V8引擎我就觉得恶心。
环境准备(IOS开发):
- XCode 14(带Simulator)
- watchman 2025.04.28.00(监控文件变化。
brew install watchman
) - cocoapods 1.16.2(包管理器,类似npm。
brew install cocoapods
) - 初始化RN应用:
npx @react-native-community/cli init MyFirstRN
,React版本为19,RN版本为0.79.2 - 在Mac上调试:
cd ios
pod install
cd ../
yarn run ios
- 在iPhone上调试:指南
目录
核心组件和原生组件
原生组件是指直接使用原生平台(iOS或Android)的UI组件。开发原生组件通常需要编写原生代码,因此更适合需要高度定制化和高性能的场景。iOS原生组件使用Objective-C或Swift编写,Android原生组件使用Java或Kotlin编写。核心组件是RN内置的组件,它是对原生组件的封装,官方对RN的核心组件做了以下归类(此处不浪费时间一一介绍,RN的文档是最好的说明手册,只记录后续使用过程中踩的一些坑):
- 基础组件
- View:搭建用户界面的最基础组件
- Text:显示文本内容的组件
- Image:显示图片内容的组件
- TextInput:文本输入框
- ScrollView:可滚动的容器视图
- StyleSheet:提供类似CSS样式表的样式抽象层
- 交互控件
- Button:一个简单的跨平台的按钮控件
- Switch:开关控件
- 列表视图
- FlatList:高性能的滚动列表组件
- SectionList:类似于FlatList,但是多了分组显示
- iOS独有的组件
- ActionSheetIOS:从设备底部弹出一个显示一个ActionSheet弹出框选项菜单或分享菜单
- 安卓独有的组件
- BackHandler:监听并处理设备上的返回按钮
- DrawerLayoutAndroid:渲染一个DrawerLayout抽屉布局
- PermissionsAndroid:对安卓6.0引入的权限模型的封装
- ToastAndroid:弹出一个Toast提示框
- 其他组件
- ActivityIndicator:显示一个圆形的正在加载的符号
- Alert:弹出一个提示框,显示指定的标题和信息
- Animated:易于使用和维护的动画库,可生成流畅而强大的动画
- Dimensions:获取设备尺寸
- KeyboardAvoidingView:一种视图容器,可以随键盘的升起而移动
- Linking:提供了一个通用的接口来调用其他应用或被其他应用调起
- Modal:一种简单的覆盖全屏的模态视图
- PixelRatio:可以获取设备的像素密度
- RefreshControl:此组件用在
ScrollView
及其衍生组件的内部,用于添加下拉刷新的功能 - StatusBar:用于控制应用顶部状态栏样式的组件
- WebView:在原生视图中显示Web内容的组件
- Picker:类似于Web端的下拉框
- Swiper:轮播图
核心组件的优势在于它们是RN的一部分,通常具有更好的跨平台一致性。
Text
1️⃣ 在RN中,所有的字符串都必须用Text
包裹,不能暴露在外面。
WebView
WebView
不是RN内置的,这玩意的使用需要先下载,详见其使用说明📖。这东西有点像Web里面的iframe
,但是在RN里它却像在我们的APP中内置了一颗小型的浏览器。简单的使用见下面Demo:
import React from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
function App(): React.JSX.Element {
return (
<View style={{
backgroundColor: 'pink',
height: '100%',
paddingTop: 50
}}>
<WebView source={{ uri: 'https://baidu.com' }} />
<WebView
originWhitelist={[ '*' ]}
// originWhitelist={['*']} 的作用是允许 WebView 加载所有来源的 URL。
// 如果不设置originWhitelist,WebView默认只允许加载http和https协议的 URL,并且域名必须匹配应用的域名(这在某些情况下可能是默认的原点白名单)。
source={{ html: '<h1>Hello world</h1>' }}
/>
</View>
);
}
Picker
Picker
同样不是RN内置的,详见其使用说明📖。简单的使用如下:
import React from 'react';
import {View} from 'react-native';
import {Picker} from '@react-native-picker/picker';
function App(): React.JSX.Element {
const [selectedLanguage, setSelectedLanguage] = React.useState();
return (
<View style={{backgroundColor: 'pink', height: '100%', paddingTop: 50}}>
<Picker
selectedValue={selectedLanguage}
onValueChange={(itemValue, _itemIndex) =>
setSelectedLanguage(itemValue)
}>
<Picker.Item label="Java" value="java" />
<Picker.Item label="JavaScript" value="js" />
</Picker>
</View>
);
}
Swiper
详细使用见使用说明📖。
其他问题
1️⃣ RN的项目的编程语言是JS(TS),如果我非要用原生组件则意味着要写其他语言,这还怎么整合?还是以iOS开发为例,封装原生组件的过程为:
- 创建一个新的Objective-C或Swift类
- 使用RCTBridgeModule协议来注册模块
- 在类中实现需要的功能和方法
- 在RN项目中使用这个组件
困得一批,先睡觉了明天再学 🥱