目录
[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的运行环境 (详细步骤可以参考官方文档)
- 在 app -> build.gradle文件中添加RN运行的依赖库 ==注意版本号==
//此处的版本号一定要与你的RN工程的版本号对应上,否则无法编译通过 版本格式一定要带两个小数点格式
implementation "com.facebook.react:react-native:0.59.10"
- 在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()
}
}
- 在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);
}
-
在你的RN空工程的项目目录将服务起来 npm start
-
然后编译运行你的Android原生工程 看是否会显示RN空工程的默认界面来判断上述配置是否正确
开始集成RN项目
RN的android工程默认实在RN的根目录android文件夹中,所以你执行react-native link的时候它自动连接修改了目录下的android工程,所以我们需要手动在你的Android工程中去link你所用到的所有的三方库
- 打开你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')
- 查看你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')
- 查看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()
))
- 修改Project -> build.gradle 文件 添加变量 因为第三方库中使用到了一些环境变量
buildscript {
...
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 16
compileSdkVersion = 28
targetSdkVersion = 28
supportLibVersion = "28.0.0"
}
...
}
END 编译运行
常见问题注意点 具体情况查看react-native run-android的时候提示的失败日志
- 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'
- 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
}
}
- 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