React Native 入门踩坑

6 篇文章 0 订阅
3 篇文章 0 订阅

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

开发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模块

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值