开发环境搭建及环境变量配置

开发rn第一步需要配置安卓环境

android studio下载地址: https://developer.android.google.cn/studio/archive

参考官方文档 使用科学的上网方式配置即可

官网参考地址: https://www.react-native.cn/docs/environment-setup

我的环境 macos+ 安卓;

初始化项目

npx react-native init ProjectName
cd 项目文件
yarn install

运行官方demo

项目初始化完成 我们先来跑起来;

选用网易mumu模拟器来运行;

参考地址: https://blog.csdn.net/S3328047358/article/details/119324911

配置好 网易mumu

npm run start // 启动服务 开发调试期间不要关闭 一般运行在8081 可使用127.0.0.1:8081访问查看
npm run android //  随后可以看到 demo被打包运行在模拟器上
// 开发工程有问题 不能解决 尝试重新运行

## 调试: 标签结构,控制台,网络请求

方式一: 谷歌浏览器 查看控制台及网络请求

点击 摇一摇 一次不行 多点几次, 会弹出开发者菜单


点击 Debug 会自动打开localhost: 8081

打开控制台 查看输出

网络请求需要添加代码才能查看

找到项目的入口文件 index.js, 加入以下代码即可

GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest

方式二: 推荐使用 react-native-debugger  三方面都可调试

下载软件: https://github.com/jhen0409/react-native-debugger

先启动软件;

在到模拟器中启动 开发者菜单 点击debug

这样模拟器和调试器就会链接在一起啦

标签结构便捷查看参考官方文档:

https://www.react-native.cn/docs/debugging#integration-with-react-native-inspector

控制台直接看即可

网络请求需要修改配置看:

菜单栏Debugger => openConfig file => defaultNetworkInspect 改成 true

方式三: 真机调试

参考: https://www.react-native.cn/docs/running-on-device

修改目录结构

配置路由

使用官方推荐的 react-navigation: https://reactnavigation.org/docs/stack-navigator/

安装

npm install @react-navigation/native

npm install @react-navigation/native-stack

路由依赖

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context

react-navigation路由思路和react-router的思路是相同的 都是组件化的路由, 路由配置在哪里 只要和地址匹配就会被渲染;

### 路由基本使用:

// App.js 文件
import React from 'react';
import { View  } from 'react-native';
import Nav from './src/routers/nav';class App extends React.Component {constructor(props) {super(props)}render(){return (<View style={{flex: 1}}><Nav></Nav></View>)}
}export default App;
//  /src/routers/nav.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
// 导入导航容器
import { createNativeStackNavigator } from '@react-navigation/native-stack';
//  导入创建堆栈导航方法
import Login from '../pages/login';
import Home from '../pages/home';
//创建导航
const Stack = createNativeStackNavigator();class Nav extends React.Component {render(){return (<NavigationContainer>{/* initialRouteName  初始默认路由 可用字段动态渲染 如不设置默认路由, 则会自动匹配第一个路由页面*/}{/* screenOptions  设置所有导航栏默认样式 */}<Stack.Navigator initialRouteName='login' screenOptions={{headerStyle: {backgroundColor: '#f4511e',},headerTintColor: '#fff',headerTitleStyle: {fontWeight: 'bold',},}}><Stack.Screen name="login" component={Login} />{/* options 设置顶部页面标题及样式 */}<Stack.Screen name="home" component={Home} options={{headerShown: false,  //是否显示标题title: '首页',headerStyle: {backgroundColor: '#f4511e',},headerTintColor: '#fff',headerTitleStyle: {fontWeight: 'bold',}}}/></Stack.Navigator></NavigationContainer>)}
}export default Nav
// /src/pages/home/index.js  路由跳转及传参import React from 'react';
import { View, Text, Button } from 'react-native';class Home extends React.Component {constructor(props){super(props)console.log('home页面');}toLoginWidthParams = () => {this.props.navigation.push('login', {con: '传递参数',id: '123'});// navigation.push('Details')        切换页面// navigation.replace('Details')     替换页面// navigation.goBack()               返回// navigation.popToTop()             回到最顶层页面}toLogin = () => {console.log('去登录页面');this.props.navigation.navigate('login');}render() {return (<View style={{flex: 1}}><View style={{color: 'red',fontSize: 14, flex: 1}}><Text>首页内容</Text><Button title="去登录页面1" onPress={this.toLogin}></Button><Button title="带参数去登录页面" onPress={this.toLoginWidthParams}></Button></View></View>)}
}export default Home;
// /src/pages/login/index.js   路由参数接受import React from 'react';
import { View, Text, Button } from 'react-native';class Login extends React.Component {constructor(props){super(props)}componentDidMount() {let params = this.props.route.params; //接收参数console.log('login componentDidMount', params);}toHome = () => {this.props.navigation.push('home');}render() {return (<View style={{flex: 1}}><View style={{color: 'red',fontSize: 14, flex: 1}}><Text>这是login页面</Text><Button title='去首页' onPress={this.toHome}></Button></View></View>)}
}export default Login;

嵌套及tabbar路由

npm install @react-navigation/bottom-tabs

参考地址: https://reactnavigation.org/docs/tab-based-navigation

​ https://reactnavigation.org/docs/nesting-navigators

// /src/routers/nav.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
// 导入导航容器
import { createNativeStackNavigator } from '@react-navigation/native-stack';
//  导入创建堆栈导航方法
import Login from '../pages/login';
import TabBar from '../pages/tabBar'
//创建导航
const Stack = createNativeStackNavigator();class Nav extends React.Component {render(){return (<NavigationContainer><Stack.Navigator initialRouteName='tabBar'><Stack.Screen name="tabBar" component={TabBar} options={{headerShown: false}}/><Stack.Screen name="login" component={Login} /></Stack.Navigator></NavigationContainer>)}
}export default Nav;
// /src/pages/tabbar/index.js
import React from 'react';
import { View, Text } from 'react-native';
// 官方推荐库
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';import Home from '../home';
import Articles from '../articles';
//创建导航
const Tab = createBottomTabNavigator();class TabBar extends React.Component {constructor(props) {super(props)}render(){return (<View style={{flex: 1}}><View style={{flex: 1}}><Tab.Navigator initialRouteName='home' screenOptions={({ route }) => ({tabBarIcon: ({ focused, size }) => {// 可以返回任何组件内容, 但一般是图标let color = focused ? 'red' : 'gray';return <Text style={{ fontFamily: "iconfont", color, fontSize: 30 }} >图标</Text>;},})}tabBarOptions={{activeTintColor: 'red',inactiveTintColor: 'gray',}}>{/* options 设置顶部页面标题及样式 */}<Tab.Screen name="home" component={Home} options={{headerShown: false,tabBarBadge: 3,}}/><Tab.Screen name="articles" component={Articles} options={{headerShown: false}}/></Tab.Navigator></View></View>)}
}export default TabBar;
// /src/pages/home/index.js
import React from 'react';
import { View, Text, Button } from 'react-native';class Home extends React.Component {constructor(props){super(props)console.log('home页面');}toLoginWidthParams = () => {this.props.navigation.push('login', {con: '传递参数',id: '123'});}toLogin = () => {console.log('去登录页面');this.props.navigation.navigate('login');}render() {return (<View style={{flex: 1}}><View style={{color: 'red',fontSize: 14, flex: 1}}><Text>首页内容</Text><Button title="去登录页面1" onPress={this.toLogin}></Button><Button title="带参数去登录页面" onPress={this.toLoginWidthParams}></Button></View></View>)}
}export default Home;

// /src/pages/articles/index.js
import React from 'react';
import { View, Text, Button } from 'react-native';class Articles extends React.Component {constructor(props){super(props)console.log('Articles组件');}componentDidMount() {let params = this.props.route.params; //接收参数console.log('componentDidMount', params);}goHome = () => {// this.props.navigation.push('home');// 本页面跳转 home 页 需要用这个方法; push方法在嵌套路由无效果this.props.navigation.navigate('home');}render() {return (<View style={{flex: 1}}><View style={{color: 'red',fontSize: 14, flex: 1}}><Text>这是Articles页面</Text><Button title="去首页" onPress={this.goHome}></Button></View></View>)}
}
export default Articles;

// /src/pages/login/index.js
import React from 'react';
import { View, Text, Button } from 'react-native';class Login extends React.Component {constructor(props){super(props)}componentDidMount() {let params = this.props.route.params; //接收参数console.log('login componentDidMount', params);}goArticle = () => {// 嵌套路由导航切换 使用此方法 不带参数this.props.navigation.navigate('articles');// 带参数跳转方式// this.props.navigation.navigate('tabBar', { screen: 'articles', params: { con: '传递参数', id: '123' }});}render() {return (<View style={{flex: 1}}><View style={{color: 'red',fontSize: 14, flex: 1}}><Text>这是login页面</Text><Button title='去文章页面' onPress={this.goArticle}></Button></View></View>)}
}export default Login;

*** 路由方面遗留一个问题: rn的路由能否像react-router使用高阶组件实现路由守卫?

暂时未找到解决办法, 只能根据实际的操作 在进行判断.

项目中引入iconfont

  1. 在字体图标网站上下载 字体

  2. 然后拷贝 ttf后缀的文件到 android\app\src\main\assets\fonts中 如果没有assets文件夹可以新建一个

  3. 然后 给 Text 标签 设置

     <Text style={{ fontFamily: "iconfont", color: "red" }} >{'\ue82b'}</Text>
    
  4. 然后记得重启项目

数据共享

父子组件传值,兄弟组件传值,与react中一样

参考: https://blog.csdn.net/S3328047358/article/details/118355972

### 无关系组件传值-Mobx简单入门

react中使用redux ,在rn中官方推荐使用mobx上手难度小于redux

中文文档: https://cn.mobx.js.org/

其他参考文档: https://blog.csdn.net/xiapi3/article/details/106901684/

https://blog.csdn.net/zjscy666/article/details/107905684

  1. 安装依赖

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

      plugins: [['@babel/plugin-proposal-decorators', { 'legacy': true }]]
    
  3. /src/mobx.index.js

    import { observable, action, makeObservable, computed } from "mobx";class RootStore {constructor(){// 最新版本的mobx 都要加这个 不然会获取不到修改后的值makeObservable(this)}// observable 表示数据可监控 表示是全局数据@observable name = "hello123";// action行为 表示 changeName是个可以修改全局共享数据的方法@action changeName(name) {this.name = name;}// 使用方法和name一样直接get即可@computed get total() {let newName = this.name + '最新的name值';return  newName;}
    }
    export default new RootStore();
  4. App.js

    import React from 'react';
    import { View  } from 'react-native';
    import Nav from './src/routers/nav';
    // 引入store
    import rootStore from "./src/mobx";
    // 使用Provider使得所有组件都可访问store
    import { Provider} from "mobx-react";class App extends React.Component {constructor(props) {super(props)}render(){return (<View style={{flex: 1}}><Provider rootStore={rootStore}><Nav></Nav></Provider></View>)}
    }
    export default App;
    
  5. /src/pages/home/index.js

    import React from 'react';
    import { View, Text, Button } from 'react-native';
    import {inject,observer } from "mobx-react";@inject("rootStore") // 注入 用来获取 全局数据的
    @observer //  当全局发生改变了  组件的重新渲染 从而显示最新的数据
    class Home extends React.Component {constructor(props){super(props)console.log('home组件 this.props.rootStore.name', this.props.rootStore.name);}toLogin = () => {this.props.navigation.navigate('login');}toChangeName = () => {console.log('toChangeName');this.props.rootStore.changeName(Date.now())}render() {return (<View style={{flex: 1}}><View style={{color: 'red',fontSize: 14, flex: 1}}><Text>这是home页面rootStore的name---{this.props.rootStore.name}</Text><Text>rootStore:get total---{this.props.rootStore.total}</Text><Button title="去登录页面" onPress={this.toLogin}></Button><Button title="修改store-name" onPress={this.toChangeName}></Button></View></View>)}
    }export default Home;
    
  6. /src/pages/articles/index.js

    import React from 'react';
    import { View, Text, Button } from 'react-native';
    import {inject,observer } from "mobx-react";@inject("rootStore") // 注入 用来获取 全局数据的
    @observer //  当全局发生改变了  组件的重新渲染 从而显示最新的数据
    class Articles extends React.Component {constructor(props){super(props)console.log('Articles组件');}componentDidMount() {let params = this.props.route.params; //接收参数console.log('componentDidMount', params);}goHome = () => {this.props.navigation.navigate('home');}render() {return (<View style={{flex: 1}}><View style={{color: 'red',fontSize: 14, flex: 1}}><Text>这是Articles页面</Text><Text>rootStore: name---{this.props.rootStore.name}</Text><Text>rootStore:get total---{this.props.rootStore.total}</Text><Button title="去首页" onPress={this.goHome}></Button></View></View>)}
    }
    export default Articles;
    

Mobx模块化使用

目录划分:

截图6

  1. /src/mobx/index.js

    import NumberStore from "./modules/number";
    import UserStore from './modules/user';export default {NumberStore,UserStore,
    }
    
  2. /src/mobx/modules/number.js

    import { observable, action, makeObservable, computed } from "mobx";class NumberStore {constructor(){makeObservable(this)}// observable 表示数据可监控 表示是全局数据@observable name = "hello123";// action行为 表示 changeName是个可以修改全局共享数据的方法@action changeName(name) {this.name = name;}// 使用方法和name一样直接get即可@computed get total() {let newName = this.name + '最新的name值';return  newName;}
    }
    export default new NumberStore();
    
  3. /src/mobx/modules/user.js

    import { observable, action, makeObservable } from "mobx";class UserStore {constructor(){makeObservable(this)}@observable userId = "userId123456";@action changeUserId(id) {this.userId = id;}
    }export default new UserStore();
  4. App.js

    import rootStore from "./src/mobx";
    <Provider {...rootStore}></Provider>
  5. /src/pages/home/index.js

    @inject("NumberStore", "UserStore")
    @observer
    class Home extends React.Component {constructor(props){super(props)console.log('NumberStore.name', this.props.NumberStore.name);console.log('UserStore', this.props.UserStore.userId);}
    }
    

持久化数据存储

rn中没有localstorage, 并且早期提供的方法已无效, 需要使用第三方库实现数据的持久化存储.

react-native-storage: https://github.com/sunnylqm/react-native-storage

打包上线

安卓打包

https://www.react-native.cn/docs/signed-apk-android

按照官方文档操作即可

其他内容

ui组件库:
React Native Elements: https://reactnativeelements.com/docs/
Ant Design: https://rn.mobile.ant.design/docs/react/introduce-cn
NativeBase: https://github.com/GeekyAnts/NativeBase#6-components
动画库: https://github.com/lottie-react-native/lottie-react-native
官方推荐第三方库大全:
https://github.com/jondot/awesome-react-native
https://github.com/reactnativecn/react-native-guide

网盘下载基础参考文档:
链接: https://pan.baidu.com/s/1NAE-_nCtg_WY0LTmstEFSQ 密码: rr2c

最后: 更多内容请阅读官网入门文档模块 组件模块 及API模块

React Native 入门踩坑相关推荐

  1. linux平台安装React Native遇到的坑

    3年前我在windows平台安装过React Native,我一直都记忆犹新,那个时候facebook刚推出支持安卓,然后花了一天的时间在自己的window电脑上配置好了,还是很兴奋的,安装博客地址如 ...

  2. React Native 入门实战视频教程(36 个视频)

    React Native 入门实战视频教程(36 个视频) #1 React Native 课程介绍「02:14」 #2 搭建 React Native 开发与运行环境跑起来「05:07」 #3 演示 ...

  3. CMT2380/HC32L110入门踩坑记录

    CMT2380/HC32L110入门踩坑记录 写在前面 1.空白工程启动文件的问题 2.RTC时钟问题 3.UART格式化输出的问题 4.SysTick进行延时 5.SW调试卡住或运行后卡住 6.pr ...

  4. 全志哪吒D1-H Tina Linux Ubuntu 22.04入门踩坑日记

    哪吒D1-H Tina Linux入门踩坑日记 系统环境 源码编译 mklibs-readelf的C++标准问题 m4的SIGSTKSZ问题 libfakeroot的_STAT_VER问题 read_ ...

  5. React Native 入门实战视频教程(37 个视频)

    我这里有视频教程,全部是我自己辛苦录的,有兴趣的可以看下. React Native 入门实战视频教程(37 个视频) 从零开始入门学习 React Native 开发,手把手教你写 App 项目 # ...

  6. React Native 入门实战视频教程(4 个视频)

    React Native 入门实战视频教程(4 个视频) #1 React Native 课程介绍「02:14」 #2 搭建 React Native 开发与运行环境跑起来「05:07」 #3 演示在 ...

  7. 微信小程序入门踩坑记(妥妥的干货,新手快快看过来)

    初次上手微信小程序,各种踩坑各种百度,草草扫过官网的文字,呃....表示记不住不想看,然后看了一本入门基础, 诺,就这本啦(链接:https://pan.baidu.com/s/15hKlDNpowU ...

  8. React Native入门(十二)之使用第三方字体文件

    前言 项目中需要展示一些别的平面或者其他民族文字时,需要使用该文字对应的字体文件,一般来说都是.ttf的. 在React Native中,使用字体文件就是在style中设置fontFamily属性! ...

  9. 给iOS开发者的React Native入门使用教程

    目录 一. 原生iOS项目集成React Native 二. 原生跳转RN页面 三. 显示豆瓣热门电影列表 四. 改为导航 五.完整源代码 一. 原生iOS项目集成React Native 创建一个新 ...

最新文章

  1. html层次选择器例题,JQuery 层次选择器的例子
  2. 数据库索引的实现原理及查询优化
  3. Mac,WIN下支撑 IPV6的 sftp客户端
  4. 【笔记】用正则匹配字符串的方法摘抄
  5. 微服务升级_SpringCloud Alibaba工作笔记0009---阿里云部署微服务_在内网不同机器上_报错_注册中心找不到对应的机器_遇到java.net.UnknownHostExceptio
  6. java 解析 ical_ical4j 实现ICS文件的生成和解析
  7. 关掉云存储后噪声 海康摄像头_万物互联 海量数据如何实现更好的存储和应用...
  8. html实现横向轮播,js实现横向轮播效果
  9. windows程序设计-王
  10. polkit启动失败_Linux MySQL 常见无法启动或启动异常的解决方案
  11. IP地址 网关是什么?网络概念
  12. 打造黑苹果(五)设置MACOS系统盘引导,以及安装驱动
  13. 深度解析B端设计规范如何落地?
  14. QT Review之 QSlider(滑块)
  15. long型转String(*)
  16. 开源无国界?你开源出去的代码, 可能有一天你自己都不能用了!
  17. 实验三 密码破解技术
  18. SQL Server 数据库基本操作入门篇【1】
  19. cscript和wscript之间的区别
  20. input自适应高度

热门文章

  1. git连接github远程仓库
  2. idea 刷新 项目 中新增的 文件
  3. mysql 二进制转字符串_将数据库的二进制转换为字符串
  4. 什么是单点登录及作用
  5. Eric6 IDE的安装和使用
  6. 用计算机解决问题的例子,电脑故障经典案例与解决方法20个
  7. Ruby_11_多线程と包管理
  8. html图片自动在div里放大,css图片自适应div大小怎么做
  9. 小程序教程1:初识小程序,快速搭建一个小程序项目
  10. 计算机英语教学教案模板,关于英语教学设计模板