ReactNative 基础整理

1,888 阅读11分钟

目录

[TOC]

React

JSX

Props属性

State

生命周期

性能优化

样式

简介

React-Native的样式基本上实现的是一个css的样式子集,所以会有所区别。

基本写法:

  • 外联布局:style={styles.container}
  • 内联布局:style={{flex:1,width:50,height:100}}
  • 多个布局:style={[styles.container,{width:50,height:100}]}

常用属性

Text文本

属性名 取值 描述 CSS对比
color -- -- 对应 CSS 中的 color 属性
fontFamily -- -- 对应 CSS 中的 font-family 属性
fontSize -- -- 对应 CSS 中的 font-size 属性
fontStyle -- -- normal, italic 对应 CSS 中的 font-style 属性,但阉割了 oblique 取值
fontWeight -- -- normal, bold 100~900 对应 CSS 中的 font-weight 属性,但阉割了 bolder, lighter 取值
lineHeight -- -- 对应 CSS 中的 line-height 属性
textAlign -- -- auto, left, right, center, justifyiOS 对应 CSS 中的 text-align
textAlignVerticalAndroid -- -- auto, top, bottom, center 对应 CSS 中的 vertical-align 属性,增加了 auto 取值,center 取代了 middle,并阉割了 baseline, sub 等值
textShadowColor -- -- 对应 CSS 中的 text-shadow 属性中的颜色定义
textShadowOffset -- -- 对应 CSS 中的 text-shadow 属性中的阴影偏移定义
textShadowRadius -- -- 在 CSS 中,阴影的圆角大小取决于元素的圆角定义,不需要额外定义
letterSpacingiOS -- -- 对应 CSS 中的 letter-spacing 属性,但取值不同
textDecorationColoriOS -- -- 对应 CSS 中的 text-decoration-color 属性
textDecorationLineiOS -- -- none, underline, line-through, underline line-through
textDecorationStyleiOS -- -- solid, double, dotted, dashed 对应 CSS 中的 text-decoration-style 属性,但阉割了 wavy 取值
writingDirectioniOS -- -- auto, ltr, rtl 对应 CSS 中的 direction 属性,增加了 auto 取值

Dimension 尺寸

属性名 取值 描述 CSS对比
width -- -- 对应 CSS 中的 width 属性
height -- -- 对应 CSS 中的 height 属性

Positioning 定位

属性名 取值 描述 CSS对比
position -- -- absolute, relative 对应 CSS 中的 position 属性,但阉割了 static, fixed 取值
top -- -- 对应 CSS 中的 top 属性
right -- -- 对应 CSS 中的 right 属性
bottom -- -- 对应 CSS 中的 bottom 属性
left -- -- 对应 CSS 中的 left 属性

Margin外部边距

属性名 取值 描述 CSS对比
margin -- -- 对应 CSS 中的 margin 属性,不同的是,只能定义一个参数,用以表示上、右、下、左4个方位的外补白
marginHorizontal -- -- CSS中没有对应的属性,相当于同时设置marginRight和marginLeft
marginVertical -- -- CSS中没有对应的属性,相当于同时设置marginTop和marginBottom
marginTop -- -- 对应 CSS 中的 margin-top 属性
marginRight -- -- 对应 CSS 中的 margin-right 属性
marginBottom -- -- 对应 CSS 中的 margin-bottom 属性
marginLeft -- -- 对应 CSS 中的 margin-left 属性

Padding 内部边距

属性名 取值 描述 CSS对比
padding -- -- 对应 CSS 中的 padding 属性,不同的是,只能定义一个参数,用以表示上、右、下、左4个方位的内补白
paddingHorizontal -- -- CSS中没有对应的属性,相当于同时设置paddingRight和paddingLeft
paddingVertical -- -- CSS中没有对应的属性,相当于同时设置paddingTop和paddingBottom
paddingTop -- -- 对应 CSS 中的 padding-top 属性
paddingRight -- -- 对应 CSS 中的 padding-right 属性
paddingBottom -- -- 对应 CSS 中的 padding-bottom 属性
paddingLeft -- -- 对应 CSS 中的 padding-left 属性

Border 边框

属性名 取值 描述 CSS对比
borderStyle -- -- solid, dotted, dashed 对应 CSS 中的 border-style 属性,但阉割了 none, hidden, double, groove, ridge, inset, outset 取值,且无方向分拆属性
borderWidth -- -- 对应 CSS 中的 border-width 属性
borderTopWidth -- -- 对应 CSS 中的 border-top-width 属性
borderRightWidth -- -- 对应 CSS 中的 border-right-width 属性
borderBottomWidth -- -- 对应 CSS 中的 border-bottom-width 属性
borderLeftWidth -- -- 对应 CSS 中的 border-left-width 属性
borderColor -- -- 对应 CSS 中的 border-color 属性
borderTopColor -- -- 对应 CSS 中的 border-top-color 属性
borderRightColor -- -- 对应 CSS 中的 border-right-color 属性
borderBottomColor -- -- 对应 CSS 中的 border-bottom-color 属性
borderLeftColor -- -- 对应 CSS 中的 border-left-color 属性
borderRadius -- -- 对应 CSS 中的 border-radius 属性
borderTopLeftRadius -- -- 对应 CSS 中的 border-top-left-radius 属性
borderTopRightRadius -- -- 对应 CSS 中的 border-top-right-radius 属性
borderBottomLeftRadius -- -- 对应 CSS 中的 border-bottom-left-radius 属性
borderBottomRightRadius -- -- 对应 CSS 中的 border-bottom-right-radius 属性
shadowColor -- -- 对应 CSS 中的 box-shadow 属性中的颜色定义
shadowOffset -- -- {width: ,height: } 对应 CSS 中的 box-shadow 属性中的阴影偏移定义
shadowRadius -- -- 在 CSS 中,阴影的圆角大小取决于元素的圆角定义,不需要额外定义
shadowOpacity -- -- 对应 CSS 中的 box-shadow 属性中的阴影透明度定义

Background 背景

属性名 取值 描述 CSS对比
backgroundColor -- 对应 CSS 中的 background-color 属性

Transform 转换

属性名 取值 描述 CSS对比
transform [{perspective: number}, {rotate: string}, {rotateX: string}, {rotateY: string}, {rotateZ: string}, {scale: number}, {scaleX: number}, {scaleY: number}, {translateX: number}, {translateY: number}, {skewX: string}, {skewY: string}] -- 对应 CSS 中的 transform 属性
transformMatrix -- -- TransformMatrixPropType 类似于 CSS 中 transform 属性的 matrix() 和 matrix3d() 函数
backfaceVisibility visible, hidden -- 对应 CSS 中的 backface-visibility 属性

Other 其他

属性名 取值 描述 CSS对比
opacity -- -- 对应 CSS 中的 opacity 属性
overflow visible, hidden -- 对应 CSS 中的 overflow 属性,但阉割了 scroll, auto 取值
elevationAndroid -- -- CSS中没有对应的属性,只在 Android5.0+ 上有效
resizeMode cover, contain, stretch -- CSS中没有对应的属性,可以参考 background-size 属性
overlayColorAndroid -- -- CSS中没有对应的属性,当图像有圆角时,将角落都充满一种颜色
tintColoriOS -- -- CSS中没有对应的属性,iOS 图像上特殊的色彩,改变不透明像素的颜色

Values取值

Color 颜色

React-Native 支持了 CSS 中大部分的颜色类型:

  • #f00 (#rgb)
  • #f00c (#rgba):CSS 中无对应的值
  • #ff0000 (#rrggbb)
  • #ff0000cc (#rrggbbaa):CSS 中无对应的值
  • rgb(255, 0, 0)
  • rgba(255, 0, 0, 0.9)
  • hsl(360, 100%, 100%)
  • hsla(360, 100%, 100%, 0.9)
  • transparent
  • Color Name:支持了 基本颜色关键字 和 拓展颜色关键字,但不支持 28个系统颜色;

Number 数值

在 React-Native 中,目前仅支持 Number 这一种长度取值。默认缺省了 pt 单位,详细请看 Units 单位 部分。

单位

Pt 点

在 React-Native 中,并不支持百分比单位,目前只支持一种单位,即 pt 绝对长度单位,同时,你在定义时不需要加单位,例如:


<View style={{width: 100, height: 50}}></View>
var styles = StyleSheet.create({
    box: {
        width: 100,
        height: 50
    }
});

布局

React Native Flex

名称 注解 类型
flex 弹性布局,与Android 的weight作用一样 number
flexDirection 改变主轴方向 string
justifyContent 控制主轴的排列方式 string
alignItems 控制交叉轴的排列方式 string
flexWrap 控制换行方式 string
alignSelf 控制自身在主轴方向上的布局方式 string
flexBasis 设置主轴方向上的初始值 string
flexGrow 设置child的放大比例 number
flexShrink 设置child的缩小比例 number

flex

他是通过数值控制元素在主轴方向上的弹性,类似Android的weight属性,有三种状态:正数,负数,零

flex:1 一般表示撑满整个父容器

flex:0 没什么意义,控件就会自动根据宽高来固定显示元素

flexDirection

控制元素的排列方向,就是声明主轴的方向

  • row: child水平方向排列
  • column: child竖直方向排列(默认)
  • row-reverse: child水平方向反向排列
  • column-reverse: child竖直方向反向排列

justifyContent

固定好主轴的方向之后通过该属性控制元素在主轴方向上的分布方式.

  • flex-start: child对齐主轴的起点(默认)
  • flex-end: child对齐主轴的终点
  • center: child居中对齐主轴
  • space-between: child在主轴方向相邻child等间距对齐,首尾child与父容器对齐
  • space-around: child在主轴方向相邻child等间距对齐,首尾child与父容器的间距相等且为相邻child间距的一半
  • space-evenly: child在主轴方向均匀分布。相邻间距与首尾间距相等

alignItems

当主轴确定之后,通过该属性控制元素在交叉轴方向上的分布方式

  • flex-start: child对齐副轴起点(默认)
  • flex-end: child对齐副轴终点
  • center: child居中对齐副轴
  • stretch: child为弹性布局时(未设置副轴方向的大小或者为auto),拉伸对齐副轴
  • baseline: 有文本存在时,child在副轴方向基于第一个文本基线对齐

flexWrap

在元素线性排列的时候如果显示不下,元素是否需要换行

  • nowrap: 不换行(默认)
  • wrap: 自动换行

alignSelf

改属性类似alignItem,但是他控制的是元素自身在交叉轴上的布局方式,默认他集成的是alignItem的属性值,如果你设置了它,它就会覆盖掉自身的alingItem属性.属性值与alignItem一样

flexBasis

设置主轴方向上的初始值,默认为auto。如果与width或者height同时存在,则会覆盖它们的值

flexGrow

设置chid的放大比例,类似于flex,空间充足时自动按比例放大,默认为0

flexShrink

设置chid的缩小比例。空间不足时自动按比例缩小,默认为0

图片适配

特定平台代码

常用组件

react-navigation (导航控制器)

安装步骤


yarn add react-navigation

yarn add react-native-gesture-handler

yarn add react-native-reanimated

yarn add react-native-screens

yarn add react-navigation-stack

//然后在podfile文件中添加
pod 'RNGestureHandler', :path => '../node_modules/react-native-gesture-handler'

//重新编译运行

StackNavigator

常用操作

跳到下一个界面, 但是不能跳到当前界面

this.props.navigation.navigate('Home')

跳到下一个界面, 但是不能跳到当前界面

this.props.navigation.push('Nearby')

返回上一个界面

this.props.navigation.goBack()

在栈控制器里, 返回到上一个界面

this.props.navigation.pop()

在栈控制器里, 返回到栈底控制器

this.props.navigation.popToTop()

TabNavigator

DrawerNavigator

Echart

安装步骤

//安装库
yarn add native-echarts 
//因为系统的webview已经不支持 所以需要换webview
yarn add react-native-webview
react-native link react-native-webview

还要改掉native-echarts里面的引用.

node_modules\native-echarts\src\index.js

node_modules\native-echarts\src\components\Echarts\index.js

import { WebView,View } from 'react-native';

这里的 WebView 去掉.添加下面的

import { WebView } from "react-native-webview";

在node_modules\native-echarts\src\components\Echarts找到tpl.html 这个文件路径

将tpl.html拷贝这个文件到android的assets这个目录下, ==(app/src/main/assets)== 没有这个目录就新建一个

更改node_modules\native-echarts\src\components\Echarts下index.js文件代码

const isoPlatform = Platform.OS === 'ios' ?'true' : 'false';

source={isoPlatform ==='true' ? require('./tpl.html'):{uri:'file:///android_asset/tpl.html'}}

iOS 很有可能会link失败 所以需要这时候手动到iOS工程目录 然后执行 pod install 命令

FlatList (列表)

常见操作

降级


npm install --save react-native@***

升级

先查看版本序列 确定要升级的版本号

//查看版本号
npm info react-native
//开始升级
npm install --save react-native@0.44.0 
//更新 系统会让你选择是否替换 一路Y即可
react-native upgrade  

常见问题

yarn add ***

该命令会导致之前导入的第三方库并且已经修改过源代码的库重新被安装 所以修改过的源代码都失效了

与原生通信交互合并等问题

与原生工程合并

Android原生工程中集成RN工程 ==0.6.0之前版本==

配置基础环境

一套原生Android工程

一套RN工程

一套与RN工程版本一致的干净的空工程

首先在Android工程中设置RN的运行环境 (详细步骤可以参考官方文档)

  1. 在 app -> build.gradle文件中添加RN运行的依赖库 ==注意版本号==
 //此处的版本号一定要与你的RN工程的版本号对应上,否则无法编译通过 版本格式一定要带两个小数点格式
 implementation "com.facebook.react:react-native:0.59.10"
 
  1. 在Project -> build.gradle中添加加载RN的android模块地址,就是你RN工程的node_modules的地址

allprojects->repositories节点下 maven最好在jcenter之前,因为jcenter容易慢导致maven中的下载失败

 maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        
        
//完整代码
allprojects {
    repositories {
        google()
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "/Users/yanfapersagy/Desktop/BIMProject_RN/BIMProject_RN/node_modules/react-native/android"
        }
        jcenter()
    }
}
  1. 在MainActiviety集成ReactRootView作为显示RN的容器组件 方便测试
//先让Activity继承 DefaultHardwareBackBtnHandler 接口
public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler 

//添加属性
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;

//在onCreate函数中初始化容器并设置各种属性

mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())//*************注意此处的Application 
                .setCurrentActivity(this)
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index")
                .addPackages(Arrays.<ReactPackage>asList(
                        new MainReactPackage(),
                        new ReanimatedPackage(),
                        new ImagePickerPackage(),
                        new RNCameraPackage(),
                        new RNScreensPackage(),
                        new RNCWebViewPackage(),
                        new RNGestureHandlerPackage()
                ))
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();
        // 注意这里的MyReactNativeApp必须对应“index.js”中的
        // “AppRegistry.registerComponent()”的第一个参数 BIMProject_RN
        mReactRootView.startReactApplication(mReactInstanceManager, "BIMProject_RN", null);//*************注意次数的name是否与RN一致

        setContentView(mReactRootView);
        
        
        
//设置生命周期,将Activity的声明周期传递给RN

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause(this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostDestroy(this);
        }
        if (mReactRootView != null) {
            mReactRootView.unmountReactApplication();
        }
    }

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

  1. 在你的RN空工程的项目目录将服务起来 npm start

  2. 然后编译运行你的Android原生工程 看是否会显示RN空工程的默认界面来判断上述配置是否正确

开始集成RN项目

RN的android工程默认实在RN的根目录android文件夹中,所以你执行react-native link的时候它自动连接修改了目录下的android工程,所以我们需要手动在你的Android工程中去link你所用到的所有的三方库

  1. 打开你RN工程中的android工程 然后将RN Android工程中的settings.gradle 文件中他手动连接的Module模块粘贴到你的Android工程中的settings.gradle文件中

==注意Module的路径==

例如:


include ':react-native-reanimated'
project(':react-native-reanimated').projectDir = new File('/Users/yanfapersagy/Desktop/BIMProject_RN/BIMProject_RN/node_modules/react-native-reanimated/android')

  1. 查看你RN Android工程的app->build.gradle文件中dependencies节点中都implementation哪些Module 然后粘贴到你的Android工程中

例如:


implementation project(':react-native-reanimated')
implementation project(':react-native-image-picker')
implementation project(':react-native-camera')
implementation project(':react-native-screens')
implementation project(':react-native-webview')
implementation project(':react-native-gesture-handler')
    
  1. 查看RN Android工程中自定义的Application文件中都添加了哪些Package 然后拷贝到你的MainActivity中

例如:


mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setCurrentActivity(this)
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index")
                .addPackages(Arrays.<ReactPackage>asList(
                        new MainReactPackage(),
                        new ReanimatedPackage(),
                        new ImagePickerPackage(),
                        new RNCameraPackage(),
                        new RNScreensPackage(),
                        new RNCWebViewPackage(),
                        new RNGestureHandlerPackage()
                ))
                
  1. 修改Project -> build.gradle 文件 添加变量 因为第三方库中使用到了一些环境变量
buildscript {
    ...
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 16
        compileSdkVersion = 28
        targetSdkVersion = 28
        supportLibVersion = "28.0.0"
    }
    ...
}

END 编译运行

常见问题注意点 具体情况查看react-native run-android的时候提示的失败日志

  1. react-native-camera 2.11.1 编译失败

问题:

Unable to resolve dependency for ':react-native-camera@debug/compileClasspath': Could not resolve com.android.support:support-compat:27.1.1

解决方法:


//app->build.gradle android->defaultConfig

missingDimensionStrategy 'react-native-camera', 'general'

  1. react-native- reanimated 1.2.0 版本问题无法编译

问题:

Could not get unknown property 'javaCompileProvider' for object of type com.android.build.gradle.internal.api.LibraryVariantImpl.

解决方法:


android.libraryVariants.all { variant ->
        def name = variant.name.capitalize()
        task "jar${name}"(type: Jar, dependsOn: variant.javaCompileProvider.get()) {
            from variant.javaCompileProvider.get().destinationDir
        }
}

替换为:


android.libraryVariants.all { variant ->
        def name = variant.name.capitalize()
        task "jar${name}"(type: Jar, dependsOn: variant.javaCompile) {
            from variant.javaCompile.destinationDir
        }
}

  1. react-navigation 各种莫名其妙的问题

//RN项目根目录执行
npm i jetifier
npx jetify

iOS原生工程集成RN工程

ReactNative 命令生成bundle文件

命令 在npm 目录下 新建bundle目录,然后在在bundle目录下新建 android 和ios 目录

如果是在原生的程序中集成RN 原生的Android程序默认加载ios.android.bundle文件目录是 ==Android/app/src/main/assets== 所以此处命令需要灵活更改

Android:


react-native bundle --entry-file index.js --bundle-output ./bundle/android/index.android.bundle --platform android --assets-dest ./bundle/android --dev false

iOS


react-native bundle --entry-file index.js --bundle-output ./bundle/ios/index.ios.jsbundle --platform ios --assets-dest ./bundle/ios --dev false

  • --entry 入口js文件,android系统就是index.android.js,ios系统就是index.ios.js
  • --bundle-output 生成的bundle文件路径
  • --platform 平台
  • --assets-dest 图片资源的输出目录
  • --dev 是否为开发版本,打正式版的安装包时我们将其赋值为false

常用命令

项目初始化

//CD到文件目录  
react-native init *** --version ***

//CD到RN的工程根目录 启动服务
npm start

运行

//运行
react-native run ios

react-native run android

ADB

查看设备列表

//先查看设备列表 确定模拟器或者真机已经连接 同时只能保持一个设备连接状态
adb devices

设施真机连接地址 不用手动设置IP

//让连接设备自动连接8081 不用再真机上手动设置PC的IP地址
adb reverse tcp:8081 tcp:8081