环境搭建

概述

react-native 的环境搭建相比较于普通的web项目(vue、react)来说要繁琐不少,但是通过以下的方式基本都可以得到解决。

安装环境介绍

  • 操作系统:win10专业版
  • 手机:安卓手机真机一部或夜神模拟器
  • 必须安装的依赖有:Node、JDK、Yarn、Android SDK、Python2

Node的安装

  • 先到 官网 去下载node版本(使用 nvm 工具来安装也可以)
  • 老师当前是用的 12.16.3 版本
  • 管理员 身份安装 然后一直点击下一步即可

Yarn的安装

Yarn是Facebook提供的替代npm的工具,可以加速node模块的下载

1
npm install yarn -g  // 使用npm全局安装yarn 

检查是否安装成功

1
yarn -v

效果如下:

image-20200522155320956

JDK的安装与配置

Java SE Development Kit

安卓系统的APP离不开JAVA环境,因此需要下载安装JDK(1.8版本)。到该网站下载JDK

image-20200522155509416

需要注意的是单击下载之后,会跳转到一个Oracler的登陆页面,得登陆之后才可以下载,如果没有账号可以注册一
个,也是比较简单,下载完成之后,以管理身份进行l默认安装。

JDK的环境变量配置

1.右键我的电脑,点属性

image-20200522161608862

2.然后单击高级系统设置,在弹出来的对话框中单击高级,再单击环境变量

image-20200522161628275

3.在弹出来的对话框中设置如下

image-20200522161647214

4.然后在 系统变量 中找到path项单击,然后再单击下面的编辑,在弹出框中设置如下

image-20200522161712608

5.到此JDK的环境变量设置完毕,可以再次打开命令行终端,使用命令 javajavac 检测一下是否设置
成功。


image-20200522161746069

Android SDK的下载与安装

我们可以直接下载Android SDK并进行必要配置
1.首先打开 网站,然后一直向下拉,找到 SDK Tools 进行下载

image-20200522161947215

2.以管理员身份安装此软件,设置 允许使用此计算机的所有人 选项,其它一路默认到底,直到安装完成.
切记,切记,切记,重要的事情说三遍,一定记着Android SDK的安装路径,后面会打开这个管理器下载东
西

image-20200522162022143

Android SDK的下载项

1.根据RN中文网的描述,编译React Native应用需要的是Android 9版本的SDK,还需要各种组件,为
了当前以及后期的稳定,总结起来,总共需要下载:

  • Android SDK Tools 25.2.5
  • Android SDK Platform-tools 29.0.5
  • Android SDK Build-tools 29
  • Android SDK Build-tools 28.0.3
  • Android SDK Build-tools 28.0.2
  • Android SDK Build-tools 28.0.1
  • Android SDK Build-tools 28
  • Android SDK Build-tools 27
  • SDK Platform 29
  • Intel x86 Atom System Image 29
  • SDK Platform 28
  • Intel x86 Atom System Image 28
  • SDK Platform 27

2.接下来,打开SDK Manager.exe,照此截图依次下载以上SDK及组件

image-20200522162144179


image-20200522162154907


image-20200522162228056


image-20200522162257510

3.此下载的过程取决于自家的网速了,不过一般都会成功的,耐心等待安装完成即可。

Android环境变量设置

1.右键选中 此电脑 点属性,再点高级,再点环境变量,设置如下

image-20200522162417205


image-20200522162431658

2.到此,安卓的环境变量配置完成

初始化项目和打包APP到设备

打包App到手机,如果没有手机的话 打包到运行到模拟器

连接到手机

  1. 准备一台 Android 手机, 通过数据线 连接 到电脑,设置启用 USB调试

  2. 如果没有安卓手机,可以使用安卓模拟器也可以,推荐使用 夜神模拟器 ,自行百度下载安装

  3. 一般的手机在 设置 中可以直接找到 开发者选项 进行开启, 如果 找不到 , 就自行百度查一下

    image-20200522170648131

  4. 手机连接电脑成功后运行检测命令 adb devices , 如果有输出设备列表与 ID 相关的字符串就证明
    手机和电脑是连接成功了,如果没有显示设备号,则说明连接有问题,一定要保证手机和电脑是正常连接状态

    image-20200522170726891

连接到模拟器

  1. 以雷电模拟器为例,找到雷电模拟器的安装目录 里面有adb.exe可执行程序

    image-20220415100106166

  2. 打开cmd窗口,cd到此目录 或者直接在文件夹窗口直接执行cmd

  3. 连接设备 雷电模拟器设备的默认端口是5555 模拟器自行百度

    1
    2
    adb connect 127.0.0.1:5555  #连接模拟器
    adb devices #查看是否连接成功

    image-20220415100758563

初始化项目并打包到手机

建议使用使用VPN进行安装 否者有可能遇到各种各样的错误

  1. 运行 npx react-native init 项目名称 命令初始化一个 React-Native 项目, 创建时需要联网 下载 依赖
    包, 可能比较慢,取决于各自的网速,一定要耐心等待,如果出错了,则重新运行命令再次初始化即可,例
    如:

    1
    npx react-native init myApp 
  2. 使用 cd myApp 命令进行此项目文件夹,确保手机和电脑连接正常的情况下,然后再输入命令 ``adb
    devices 来检测一下手机是否正常连接,然后再使用命令 yarn android` 将APP打包到手
    机上

  3. 手机上出现如下画面,说明打包成功

    image-20200522170849831

手机屏幕投影工具

为了在电脑上看到真实的手机屏幕,可以安装手机屏幕投影工具

网上有很多工具,百度即可看到。文章使用的是 scrcpy

使用教程

  1. 下载好 工具

  2. 手机通过usb连接到电脑

  3. 双击打开工具即可

    image-20200522172425782

调试

分为两种方式

  1. 使用谷歌浏览器来调试

    1. 使用谷歌浏览器即可
    2. 不能查看标签结构
    3. 不能查看网络请求
  2. 使用rn推荐的工具 react-native-debugger来调试 (推荐使用这种方式)

    1. 可以查看标签结构
    2. 可以查看网络请求

踩坑记录

环境搭建踩坑

  1. image-20220415101425706

    解决:

    找到$ANDROID_HOME/tools/bin/目录下 执行命令

    1
    2
    sdkmanager --licenses   如果找不到或报错 说明sdkManager的版本太低 执行命令进行升级[环境jdk1.8]
    sdkmanager --update 更新 再次执行sdkmanager --licenses就会有了
  2. 错误关键字:jdk版本过低 请升级到jdk11版本

    解决:

    将jdk升级到11就可以了

  3. 错误类型:安装 Android SDK 的时候找不到jdk

    解决:

    安装前把java环境降到jdk1.8 即可

调试工具踩坑

  1. 错误描述

    1
    2
    3
    4
    5
    6
    7
    Uncaught Error: Cannot add node "1" because a node with that id is already in the Store.

    The error was thrown at /path/React Native Debugger.app/Contents/Resources/app.asar/node_modules/react-devtools-core/dist/standalone.js:48:140545
    at c.emit (/path/React Native Debugger.app/Contents/Resources/app.asar/node_modules/react-devtools-core/dist/standalone.js:48:89515)
    at /path/React Native Debugger.app/Contents/Resources/app.asar/node_modules/react-devtools-core/dist/standalone.js:48:90986
    at /path/React Native Debugger.app/Contents/Resources/app.asar/node_modules/react-devtools-core/dist/standalone.js:48:347787
    at Array.forEach (<anonymous>)

    或者

    img

解决:react-native-core与工具的版本不兼容导致的 react-native安装的时候 默认安装了一个最新版本 而工具用的是旧版 只需要对项目的react-native-core进行降级即可

在项目的package.json中,添加以下内容:

1
2
3
"resolutions": {
"react-devtools-core": "4.14.0"
}

删除node_modules文件夹,package.json.lock

当前项目下cmd执行 yarn install 即可

react native elements[路由导航]

安装

已进行过github身份验证

1
yarn add @react-native-elements/themed @react-native-elements/base

未进行github身份验证

1
2
3
4
5
# @react-native-elements/base
yarn add @react-native-elements/base@react-native-elements/react-native-elements#base

# @react-native-elements/themed
yarn add @react-native-elements/themed@react-native-elements/react-native-elements#themed

安装图标库

1
yarn add react-native-vector-icons

android/app/build.gradle中添加代码

1
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"

react-native-safe-area-context

该依赖我们上一章已经安装过了,可以跳过,它可以保证我们的APP运行在安全屏幕范围中

1
yarn add react-native-safe-area-context

使用

直接在App最外层套一层SafeAreaProvider即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// /**
// * Sample React Native App
// * https://github.com/facebook/react-native
// *
// * @format
// * @flow strict-local
// */
//

//引入导航
import React, {Component} from 'react';
import Nav from './src/route/index';
import {SafeAreaProvider} from "react-native-safe-area-context/src/SafeAreaContext";
import {Provider} from "mobx-react";

const Index = () => {
return
{/*使用自定义导航*/}
<SafeAreaProvider>
<Nav/>
</SafeAreaProvider>

}

export default Index;

封装路由导航

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import * as React from "react";

//引入页面js
import Login from "../pages/login";
import Home from "../pages/home";
const Stack = createStackNavigator();
export default () => {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{headerShown:false}}
options={{ title: 'My home' }} initialRouteName="Login">
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Home" component={Home} />
</Stack.Navigator>
</NavigationContainer>
)
}

至此,所有需要的依赖包全部安装完毕。

运行项目,会重新打包,确保应用能正常打开。

如果出现错误,可以卸载掉安装的依赖,重新安装试试。

mobx [状态共享]

react中 全局数据管理库 可以简单的实现数据的跨组件共享 类似 vue中的vuex

img

安装

  1. 安装依赖

    • mobx 核心库
    • mobx-react 方便在react中使用mobx技术的库
    • @babel/plugin-proposal-decoratorsrn 项目支持 es7 的装饰器语法的库
    1
    yarn add mobx mobx-react  @babel/plugin-proposal-decorators
  2. babel.config.js添加以下配置

    1
    2
    3
    4
    plugins: [
    ['@babel/plugin-proposal-decorators', { 'legacy': true }]
    ]

    或者在.babelrc文件里添加以下配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    {
    "presets": [
    "module:metro-react-native-babel-preset"
    ],
    "plugins": [
    [
    "@babel/plugin-proposal-decorators",
    {
    "legacy": true
    }
    ],
    [
    "@babel/transform-runtime",
    {
    "helpers": true,
    "regenerator": false
    }
    ]
    ]
    }

    使用

  3. 新建文件 mobx\index.js 用来存放 全局数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import { observable, action } from "mobx";

    class RootStore {
    // observable 表示数据可监控 表示是全局数据
    @observable name = "hello";
    // action行为 表示 changeName是个可以修改全局共享数据的方法
    @action changeName(name) {
    this.name = name;
    }
    }

    export default new RootStore();
  4. 在根组件中挂载

    通过 Provider 来挂载和传递

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    // /**
    // * Sample React Native App
    // * https://github.com/facebook/react-native
    // *
    // * @format
    // * @flow strict-local
    // */
    //

    //引入导航
    import React, {Component} from 'react';
    import Nav from './src/route/index';
    import {SafeAreaProvider} from "react-native-safe-area-context/src/SafeAreaContext";
    import {Provider} from "mobx-react";
    import rootStore from "./src/stores/RootStore";
    // const stores = {
    // rootStore,
    // // 便于引入多个 store
    // };

    const Index = () => {


    return <Provider rootStore={rootStore}>
    {/*使用自定义导航*/}
    <SafeAreaProvider>
    <Nav/>
    </SafeAreaProvider>
    </Provider>
    }

    export default Index;

  1. 其他组件中使用

    [类的使用方法]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import React, { Component } from 'react';
    import { View, Text } from 'react-native';
    import {inject,observer } from "mobx-react";

    @inject("rootStore") // 注入 用来获取 全局数据的
    @observer // 当全局发生改变了 组件的重新渲染 从而显示最新的数据
    class Sub1 extends Component {
    changeName = () => {
    // 修改全局数据
    this.props.rootStore.changeName(Date.now());
    }
    render() {
    console.log(this);
    return (
    <View><Text onPress={this.changeName}>{this.props.rootStore.name}</Text></View>
    );
    }
    }

    export default Index;

    [hook的使用方法]

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import React, {useEffect, useState} from 'react';
    import {View, Text} from 'react-native'
    import {inject, observer} from "mobx-react";

    //参数是状态共享对象
    const Index = ({baseStore}) => {
    //hook
    const [val,setVal] = useState("哈哈哈")
    //页面渲染,更新,销毁执行
    useEffect(() => {
    setVal('咦1111');
    baseStore.changeName(val)
    })

    return (
    <View>
    <Text style={{color: 'red'}}>{baseStore.userName}</Text>
    </View>

    )

    }
    //注入的状态共享对象导出的对象
    export default inject('baseStore')(observer(Index));