Published on

React Native

Authors
  • avatar
    Name
    MissTree
    Twitter

React Native 前期准备

React Native 官方文档 React Native 中文网

环境搭建

    1. 安装 Node.js
    1. 安装 JDK
    1. 安装 androiddevtools
    1. 安装 Android Studio 和 Android SDK
    1. 安装 Xcode 和 CocoaPods -- IOS环境
    • Xcode 是 Apple 开发的集成开发环境,用于开发 iOS 应用。
    • CocoaPods 是一个用于管理 iOS 项目依赖的第三方库,React Native 项目需要使用 CocoaPods 来管理依赖。
    1. 配置环境变量
    1. Hyper-V 相关设置

在window系统下只能开发 android,mac 系统可以同时开发 ios 和 android

expo cli

expo 是一个用于开发 React Native 应用的工具,它提供了一套命令行工具和一套开发环境,可以让开发者更方便地开发 React Native 应用。

# 全局安装脚手架
npm install -g expo-cli

# 创建项目
expo init MyApp
cd MyApp
# 启动项目 yarn start
expo start

# 直接创建项目
npx create-expo-app@latest

项目运行在 http://localhost:8081/ exp://192.168.142.252:8081

› Using Expo Go
› Press s │ switch to development build

› Press a │ open Android
› Press w │ open web   # 打开浏览器

› Press j │ open debugger
› Press r │ reload app
› Press m │ toggle menu
› shift+m │ more tools
› Press o │ open project code in your editor  # 打开编辑器

› Press ? │ show all commands

项目结构

react-native cli

react-native cli 是 React Native 官方提供的命令行工具,它提供了一套命令行工具和一套开发环境,可以让开发者更方便地开发 React Native 应用。

# 全局安装脚手架
npm install -g react-native-cli

# 创建项目
npx react-native init MyApp
cd MyApp
# 启动项目
npx react-native run-ios
npx react-native run-android
# 启动模拟器后时间可能有点长,需要等待
# 创建项目目录 src/compnonents src/routes src/screens src/utils

# 添加项目依赖
yarn add react-native-elements react-native-vector-icons react-native-safe-area-context

新版本替代 使用 @react-native-community/cli 代替了旧的 react-native-cli

npm install -g @react-native-community/cli
npx react-native init MyApp

SafeAreaView

react-native-safe-area-context是处理安全区域的库。提供SafeAreaView,虽然这个组件在rn中也有,但是rn中的只⽀持 ios10+,不⽀持ios和android的⽼版本。项⽬中建议选择react-native-safe-area-contex的SafeAreaView。

其他常用工具

示例代码

import React, {useState} from 'react';
import { View, Text, StyleSheet, SafeAreaView, Image,
 ImageBackground, TextInput, ScrollView,} from 'react-native';
import {Button} from 'react-native-elements';
const logo = 'https://zh-hans.reactjs.org/logo-og.png';

export default function App() {
 const [count, setCount] = useState(0);
 const [text, setText] = useState('default');
 return (
  <SafeAreaView>
    <ScrollView>
      <Text>App</Text>
      <Image source={{uri: logo}} style={styles.logo}/>
      <ImageBackground source={{uri: logo}} style={styles.logo}>
      <Text style={{color: 'white'}}>Inside</Text>
      </ImageBackground>
      <Button title={count + ''}
      onPress={() => setCount(count + 1)}
      buttonStyle={styles.btn}/>
      <TextInput value={text}
      onChangeText={txt => setText(txt)}
      style={styles.txt}/>
      <Text style={[styles.txt, {borderColor:'green'}]}>
        <Text style={styles.bold}>⽂本: </Text>
        <Text>{text}</Text>
      </Text>
      <View style={[styles.txt, {borderColor:'green'}]}>
        <Text style={styles.bold}>⽂本: </Text>
        <Text>{text}</Text>
      </View>
      {/* //! 溢出 */}
      <Text>omg:</Text>
      <Text numberOfLines={1}>{'书名'.repeat(100)}</Text>
      {/* <Text>{'书名'.repeat(1000)}</Text> */}
    </ScrollView>
  </SafeAreaView>
 );
}

const styles = StyleSheet.create({
 logo: {
  width: 100,
  height: 100,
 },
 btn: {
  width: 100,
  height: 100,
  backgroundColor: 'red',
 },
 txt: {
  width: 100,
  height: 100,
  backgroundColor: 'yellow',
 },
 bold: {
   fontWeight: 'bold',
 },
});

与其他框架的对比

React Native 与其他框架的对比

APP 开发对比

React Native UI

视图和移动

React Native UI 组件Android 视图iOS 视图web描述
<View><ViewGroup><UIView><div>支持使用弹性框、样式、一些触摸处理和可访问性控件进行布局的容器
<Text><TextView><UITextView><p>显示、设置样式、嵌套文本字符串,甚至处理触摸事件
<Image><ImageView><UIImageView><img>显示不同类型的图像
<ScrollView><ScrollView><UIScrollView><div>可包含多个组件和视图的通用滚动容器
<TextInput><EditText><UITextField><input type="text">允许用户输入文本

样式

在react native中,样式是通过StyleSheet.create()方法来创建的,这个方法接受一个对象,对象的属性名是样式名,属性值是样式值。 样式属性示例

import Dimensions from 'react-native-dimensions';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    width: Dimensions.get('window').width/4, // 获取屏幕宽度设置几分之一
    height:100
  },
  text: {
    fontSize: 20,
    color: '#000',
  },
});

样式没有继承性,Text 的样式可以继承,尺寸大小没有单位

常用组件

参考

  • TouchableOpacity: 创建一个可点击的组件
  • TouchableHighlight: 创建一个可点击的组件,并且在点击时会有一个高亮效果
  • TouchableWithoutFeedback: 创建一个可点击的组件,并且在点击时不会有任何效果
  • Modal: 创建一个模态框
  • SectionList: 创建一个列表,可以分组显示
  • Keyboard
  • Animated
  • PanResponder
  • DrawerLayoutAndroid
  • DrawerLayout
  • ViewPagerAndroid
  • ViewPager
  • WebView
  • Picker
  • Alert: 显示一个警告对话框
  • StatusBar: 状态栏组件
  • Button: 创建一个按钮
  • ActivityIndicator: 加载指示器
  • DatePickerAndroid: 显示一个日期选择器
  • DrawerLayoutAndroid: 创建一个抽屉布局
  • FlatList: 高性能列表组件
  • Image: 显示一个图片
  • KeyboardAvoidingView: 避免键盘遮挡
  • Modal: 创建一个模态框
  • Picker: 创建一个选择器

导航跳转

React Native并没有浏览器那样的历史栈,所以React Navigation就来做这件事了。

yarn add @react-navigation/native react-native-screens react-native-safe-area-context

React Navigation 提供了三种类型的导航器:

  • Stack Navigator:栈导航器,用于管理页面之间的跳转,类似于浏览器的历史栈。
    • yarn add @react-navigation/native-stack
  • Tab Navigator:标签导航器,用于在多个页面之间进行切换,类似于浏览器的标签页。
  • Drawer Navigator:抽屉导航器,用于在多个页面之间进行切换,类似于浏览器的侧边栏。

Stack Navigator

createNativeStackNavigator是⼀个函数,返回⼀个对象,这个对象⾥有两个都是React组件的属性:Screen and Navigator。注意它们的包裹关系:NavigationContainer->Navigator->Screen Screen属性:

  • name:路由名称,⽤于标识路由,必须唯⼀
  • component:该路由对应的组件
  • options:该路由的配置项,例如标题、头部样式等,也可以通过options的title修改
  • initialParams:给组件参数

Navigator属性:

  • initialRouteName:初始路由名称,默认为第一个路由
  • screenOptions:全局路由配置项,例如标题、头部样式等
// app.js
import React from 'react';
import {NavigationContainer} from '@reactnavigation/native';
import RootRouter from './RootRouter';

export deault function App () {
 return (
 <NavigationContainer>
 <RootRouter />
 </NavigationContainer>
 );
}

// RootRouter.js
import React from 'react';
import {View, Text} from 'react-native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import HomeScreen from '@/screens/HomeScreen';
import UserScreen from '@/screens/UserScreen';

const {Screen, Navigator} =createNativeStackNavigator();
export default function RootRouter() {
 return (
 // ! SafeAreaView不能写这⾥
 // <SafeAreaView>
 <Navigator>
 <Screen name="home" component={HomeScreen} />
 <Screen name="user"
 component={UserScreen}
 options={{title: '⽤户中⼼'}}
 initialParams={{name: '我是⼩明'}}
 />
 </Navigator>
 // </SafeAreaView>
 );
}

// Link跳转
<Link to={{screen: 'user', params: {id: 'jane'}}}>
 Go to Jane's profile
</Link>
// navigation.navigate('home', {screen: 'home', params: {id: 'jane'}});
// 事件跳转
<Button
 title="go home"
 onPress={() => {
 // navigation.push('home');
 // navigation.navigate('home');
 }}
 />

⻚⾯是否已经存在,执⾏navigation.navigate导致的结果是不同的。如果⻚⾯已经存在,执⾏navigation.navigate则会回到原先的⻚⾯,并且移除原先⻚⾯在历史栈中的记录。如果⻚⾯不存在,则push⼀个新的记录到历史栈中。 但是如果你执⾏navigation.navigate的时候,给⻚⾯添加了参数,那对与历史栈来说,这个记录对于历史栈就是个新的记录了。

平台特定代码

参考

import {Platform, StyleSheet} from 'react-native';

const styles = StyleSheet.create({
  height: Platform.OS === 'ios' ? 200 : 100,
});

import {Platform, StyleSheet} from 'react-native';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    ...Platform.select({
      ios: {
        backgroundColor: 'red',
      },
      android: {
        backgroundColor: 'blue',
      },
    }),
  },
});

const Component = Platform.select({
  ios: () => require('ComponentIOS'),
  android: () => require('ComponentAndroid'),
})();

<Component />;

import {Platform} from 'react-native';

if (Platform.Version === 25) {
  console.log('Running on Nougat!');
}

# 不同平台组件
BigButton.ios.js
BigButton.android.js

import BigButton from './BigButton';

注意事项

  • Hooks API 是 React Native 0.59 提供的新特性
  • 因为 JSX 语法糖的实质是调⽤React.createElement⽅法,所以你必须在⽂件头部引⽤import React from 'react'。