Skip to content

入门 ​

什么是 React Native ​

一款基于 React 的跨平台移动应用开发框架。

同类型产品

  • uniapp x:很多内容是闭源的,而且会受到小程序方面的限制
  • Inoic:古早框架,直接将web view 渲染到手机上,没办法利用一些原生功能,现在用的人较少
  • tauri:基于rust,目前还处于试验阶段,容易踩坑
  • flutter:跨段应用解决方案中最好的一个方案,但是学习成本较高。

学习前必要的知识

  • React
  • TypeScript

创建项目 ​

bash
npm create-expo-app@latest

# 或

pnpm create expo-app

项目初始文件十分复杂可以reset画面,以简化复杂度

bash
npm run reset

会询问是否将原内容保存至 example,选择 y 后,可以看到一个干净的目录。

同时原内容被保存至 exmple 文件夹中,这个文件夹如果不用的话也可以删除。

目录结构 ​

MyApp

├── app
│   ├── _layout.tsx
│   ├── index.tsx
│   └── about.tsx
│
├── assets
│
├── package.json
│
└── node_modules

系统采用了 文件路由,app下每一个 .tsx 文件都会自动生成路由。

如当前的目录结构,当访问 /about 时,会渲染 app/about.tsx 文件的内容。

其中有两个特殊的文件:

  • _layout.tsx:整个应用的布局文件,所有页面都将在这里进行渲染。
  • index.tsx:整个应用的入口文件,所有页面的路由都将从这里开始。

启动命令 ​

bash
npm run start

如果要在手机上打开,需要先下载 expo go 应用,然后扫描二维码,或输入链接。

并且确保服务器与手机在同一个网络中。

如果要在浏览器打开,只需在浏览器中输入 pn start 运行成功后提供的网址即可。

简化项目 ​

项目创建后默认会有一个相对复杂的示例,通过命令可以简化项目

bash
pn reset-project

Do you want to move existing files to /example instead of deleting them?(是否要将现有文件移动到/example,而不是删除它们?)

这里选择 y 会创建一个 /example 文件夹来存放原本的示例,不想要也可以删除。

常用组件 ​

React NativeAndroid说明
ViewViewGroup容器组件,用来包裹其他组件
TextTextView文本组件,用于显示文字
ImageImageView图片组件,用于显示图片
TextInputEditText输入框组件,用于输入文本
ScrollViewScrollView滚动视图组件,用于显示长列表
FlatListRecyclerView列表组件,用于显示长列表
ButtonButton按钮组件,用于触发操作
Pressable可点击区域
TouchableOpacity带点击透明效果的按钮
SectionList分组列表
SafeAreaView安全区域
ActivityIndicator加载动画
Modal弹窗
KeyboardAvoidingView键盘弹出时自动调整布局
StatusBar控制手机顶部状态栏
Switch开关按钮
ActivityIndicator + RefreshControl常用于下拉刷新

样式 ​

React Native 没有 XML 标签,而是使用 JavaScript 来定义样式。

需在文件中引入 StyleSheet,然后通过 StyleSheet.create 方法创建样式对象。

ts
import { StyleSheet, Text, View } from "react-native";

export default function Index() {
    return (
        <View style={styles.container}>
            <Text>标题</Text>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: "center"
    }
});

也可以直接在 Dom 上以双括号 的方式,为 style 定义样式。

js
<View
    style={{
        backgroundColor:'red',
        padding:20
    }}
>
    <Text>标题</Text>
</View>

或

生态 ​

  • 路由(expo-router)
  • 状态管理(Zustand / Redux)
  • 服务端数据(TanStack Query)
  • UI 组件库
  • 本地数据存储
  • 网络请求
  • 权限
  • 通知 / 震动 / 蓝牙等原生能力
  • 工程化

tailwind css ​

https://docs.expo.dev/guides/tailwind/

标准的 Tailwind CSS 仅支持 Web 平台,如果要在 react native 中使用,要用 NativeWind 或 Uniwind 等库。

安装 ​

详细请看:https://www.nativewind.dev/docs/getting-started/installation

根据库升级可能会有变化。

1.安装依赖

bash
pnpm add nativewind react-native-reanimated react-native-safe-area-context
pnpm add --save-dev tailwindcss@^3.4.17 prettier-plugin-tailwindcss@^0.5.11 babel-preset-expo

2.生成配置文件

bash
npx tailwindcss init

执行后会在根目录下生成 tailwind.config.js 文件。

将下面的内容复制到文件中。

js
/** @type {import('tailwindcss').Config} */
module.exports = {
  // NOTE: Update this to include the paths to all files that contain Nativewind classes.
  content: ["./App.tsx", "./components/**/*.{js,jsx,ts,tsx}"],
  presets: [require("nativewind/preset")],
  theme: {
    extend: {},
  },
  plugins: [],
}

content 表示 tailwind css 要作用于哪些文件,{} 内表示文件的后缀,现在这里写的是 App.tsx 和 components 下的 {js,jsx,ts,tsx} 文件。但是真正开发时我们想要的可能是作用域整个 src,所以可以改成:

js
/** @type {import('tailwindcss').Config} */
module.exports = {
  // NOTE: Update this to include the paths to all files that contain Nativewind classes.
  content: ["./App.tsx", "./src/**/*.{js,jsx,ts,tsx}"],
  presets: [require("nativewind/preset")],
  theme: {
    extend: {},
  },
  plugins: [],
}

3.创建global

在根下创建 global.css,并加入以下内容:

css
@tailwind base;
@tailwind components;
@tailwind utilities;

4.创建babel配置文件

在根目录创建 babel.config.js,并加入以下内容:

js
module.exports = function (api) {
    api.cache(true);
    return {
        presets: [
            ["babel-preset-expo", { jsxImportSource: "nativewind" }],
            "nativewind/babel",
        ],
    };
};

5.创建metro配置文件

在根目录创建 metro.config.js,并加入以下内容:

js
const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require('nativewind/metro');
 
const config = getDefaultConfig(__dirname)
 
module.exports = withNativeWind(config, { input: './global.css' })

注意这里 metro.config.js 创建在根路径,配置中 input 指向的是 global.css,如果位置不对要自行调整配置或 global.css 文件位置

6.导入CSS

在画面入口中导入 global.css,最新版中是 _layout.tsx,之前的入口可能是 App.js,看真实项目生成的文件结构而定

js
import "@/global.css";

或

import "./global.css";

7.修改app.json配置

在根目录找到 app.json 文件,找到 expo.web 配置

添加 bundler 配置:

json
{
    "expo": {
        "web": {
            "bundler": "metro"
        }
    }
}

问题

运行可能会出现错误:Unable to resolve module react-native-css-interop/jsx-runtime

这是由于使用pnpm无法深度扫描依赖包,导致安装nativewind时漏掉了它的子依赖 react-native-css-interop。

解决方法1:

我们可以移动 react-native-css-interop 到项目根目录的 package.json 中,然后重新安装依赖即可。(不过这种方式不推荐,因为也可能有其他包有这个问题,太繁琐。)

bash
pnpm add react-native-css-interop

解决方法2:

使用npm,npm可以进行深度扫描不会出现这个问题。

解决方法3:

参考

如果依旧想使用 pnpm,可以对 pnpm 做一些配置。

node-linker=hoisted

在之前的pnpm版本中可以写在根目录 .npmrc 中,新版本(v11)需要写在 pnpm-workspace.yaml 中。

yaml
nodeLinker: hoisted

如:

yaml
nodeLinker: hoisted
minimumReleaseAgeExclude:
  - "@expo/cli@57.0.23"
  - "@expo/metro-file-map@57.0.3"
  - "@expo/ui@57.0.17"
  - babel-preset-expo@57.0.11
  - expo-glass-effect@57.0.2
  - expo-modules-core@57.0.17
  - expo-modules-jsi@57.1.0
  - expo-router@57.0.20
  - expo@57.0.21

随后删除 node_modules 目录,重新安装依赖:

bash
pn i

包安装 ​

在 react native 中,当我们要安装一个包,且包的开头是 @expo/ 时不要直接通过包管理器安装。

如:@expo/vector-icons

当我们要安装他时应该使用:

bash
pn expo install @expo/vector-icons

这样安装有一个好处是 Expo 会自动帮我们检测匹配当前这个 react native 和 expo 的版本,不会出现兼容性的问题。