0%

react-native开发总结

简介

  • 项目总结代码地址
  • 记录开发 react-native 中各种有意思的事情
  • 最新探索,用来进行各种尝试的空间
  • 完成的探索,记录所有已经完成的模块、功能和效果
  • 中转站,暂时无用

安装

全局脚手架

1
npm i -g react-native-cli

安装基础项目

1
react-native init <项目名称>

运行

优化后的运行

  • ios:npm run ios
  • android:npm run android
  • ios and android:npm run s

原始启动

  • ios:react-native run-ios
  • android:react-native run-android

资源

未探索的资源

365 个库中寻找 77 个

新增页面需要在三个地方进行操作

  1. data 里面的 complete.js 中添加数据,方便在完成的探索中出现
  2. navigators 中的 AppStackNavigators.js 里面进行引入=>注册,使得路由正常
  3. pages 里面添加页面

优化 package.json 使开发更加方便

  • 在 scripts 中添加,如下内容:
1
2
3
"ios":"react-native run-ios",
"android":"react-native run-android",
"s":"npm run ios && npm run android",

flex 布局常用属性

  • 防止在 flex 中出现,固定元素被挤压的问题,使用 flex:1 进行优化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
display: 'flex';
flexDirection: row | row-reverse | column | column-reverse;
flexWrap: nowrap | wrap | wrap-reverse;
flexFlow: <flex-direction> | <flex-wrap>;
justifyContent: flex-start | flex-end | center | space-between | space-around;
alignItems: flex-start | flex-end | center | baseline | stretch;
alignContent: flex-start | flex-end | center | space-between | space-around | stretch;

order: <integer>;
flexGrow: <number>; /* default 0 */
flexShrink: <number>; /* default 1 */
flexBasis: <length> | auto; /* default auto */
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
alignSelf: auto | flex-start | flex-end | center | baseline | stretch;

图片

图片使用

1
<Image source={require('./my-icon.png')} />

命名规则

链接原生库

第一步

安装带原生依赖的库

1
npm install <某个带有原生依赖的库> --save

第二步

运行以下命令,它会根据 package.json 文件中的 dependencies 和 devDependencies 记录来链接所有需要链接的库

1
react-native link

开发技巧

  • 启动 hot 或者 debug 的时候,切记不要同时启动 ios and android,两者会发生冲突,导致出现程序崩溃,从而影响开发
  • 最好的方式是,启动一个 hot 或 debug,这样可以良好的进行开发;另一个手动足够了

处理触摸事件

使用”Touchable”开头的一系列组件
通过 onPress 属性接受一个点击事件的处理函数

  • 两种方式绑定事件,并处理点击范围
  • 推荐第二种,方便传递数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
_onPressButton=((item)=>{
alert(1)
console.log(item);
})
render() {
return (
<View>
<TouchableHighlight onPress={this._onPressButton}>
<View style={[S.btn,{backgroundColor:`${this.state.bg}`}]}>
<Text style={S.btnText}>{this.state.bg}</Text>
</View>
</TouchableHighlight>
<TouchableHighlight onPress={()=>{
this._onPressButton(this.state.bg)
}}>
<View style={[S.btn,{backgroundColor:`${this.state.bg}`}]}>
<Text style={S.btnText}>{this.state.bg}</Text>
</View>
</TouchableHighlight>
</View>
);
}

解决版本冲突问题

js 版本和 rn 版本出现冲突

  • Watchman 是由 Facebook 提供的监视文件系统变更的工具。安装此工具可以提高开发时的性能(packager 可以快速捕捉文件的变化从而实现实时刷新)。
  • 清除 Watchman:watchman watch-del-all
  • 清除 rn 缓存:react-native start –reset-cache

解决路由失效问题

  • createTabNavigator 要在 createStackNavigator 里面进行注册,才能够使用 createStackNavigator 具有的方法,这个是我第二次配置的时候掉进的一个坑
    this.props.navigation 属性详细说明

  • 在 createTabNavigator 里面没有 push、replace 等方法

  • 在 createStackNavigator 中存在 push、replace 等方法

AsyncStorage 保存报错

JSON value ‘‘ of type NSNull

  • 当保存值为 undefined 的时候,报错
  • 防止这种问题发生最好在 this.state 中保存初始值为空,必要时可以提醒用户

react-native 支持的 style props

  • 查看最新版属性支持情况,最简单的直接在页面使用错误的属性,然后查看报错信息 😂
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
Valid style props: [
"alignContent",
"alignItems",
"alignSelf",
"aspectRatio",
"backfaceVisibility",
"backgroundColor",
"borderBottomColor",
"borderBottomEndRadius",
"borderBottomLeftRadius",
"borderBottomRightRadius",
"borderBottomStartRadius",
"borderBottomWidth",
"borderColor",
"borderEndColor",
"borderEndWidth",
"borderLeftColor",
"borderLeftWidth",
"borderRadius",
"borderRightColor",
"borderRightWidth",
"borderStartColor",
"borderStartWidth",
"borderStyle",
"borderTopColor",
"borderTopEndRadius",
"borderTopLeftRadius",
"borderTopRightRadius",
"borderTopStartRadius",
"borderTopWidth",
"borderWidth",
"bottom",
"color",
"decomposedMatrix",
"direction",
"display",
"elevation",
"end",
"flex",
"flexBasis",
"flexDirection",
"flexGrow",
"flexShrink",
"flexWrap",
"fontFamily",
"fontSize",
"fontStyle",
"fontVariant",
"fontWeight",
"height",
"includeFontPadding",
"justifyContent",
"left",
"letterSpacing",
"lineHeight",
"margin",
"marginBottom",
"marginEnd",
"marginHorizontal",
"marginLeft",
"marginRight",
"marginStart",
"marginTop",
"marginVertical",
"maxHeight",
"maxWidth",
"minHeight",
"minWidth",
"opacity",
"overflow",
"overlayColor",
"padding",
"paddingBottom",
"paddingEnd",
"paddingHorizontal",
"paddingLeft",
"paddingRight",
"paddingStart",
"paddingTop",
"paddingVertical",
"position",
"resizeMode",
"right",
"rotation",
"scaleX",
"scaleY",
"shadowColor",
"shadowOffset",
"shadowOpacity",
"shadowRadius",
"start",
"textAlign",
"textAlignVertical",
"textDecorationColor",
"textDecorationLine",
"textDecorationStyle",
"textShadowColor",
"textShadowOffset",
"textShadowRadius",
"textTransform",
"tintColor",
"top",
"transform",
"transformMatrix",
"translateX",
"translateY",
"width",
"writingDirection",
"zIndex"
]

StatusBar 解决 android 状态栏问题

设置 StatusBar

1
2
3
4
<StatusBar
backgroundColor="transparent"
translucent
/>

设置顶部模块的样式

  • 注:padding 值需要+高度值=>height 最终值
1
2
height: 50,
paddingTop: 10,

Platform 区分 ios and android 平台

三种方法实现跨平台:

  1. Platform.OS
  2. 使用 Platform 的 select 方法
  3. 使用不能组件名:ios 使用 header.ios.js;android 使用 header.android.js
1
2
3
4
const instructions = Platform.select({
ios: 'ios',
android: 'android',
});

请求 fetch 封装

  • HttpUtils.js
    引入
1
import HttpUtils from '../../HttpUtils';

使用

  • 在全局 global.data.domain 保存请求域名
  • 请求需要 header 传递 token 的使用,global.data.token
1
2
3
4
5
6
7
8
9
10
HttpUtils.post(`${apiConfig}`, {
platform: 'ios'
},global.data.token)
.then(rtn => {
global.data.config = rtn;
// console.log(`配置=>( ${JSON.stringify(rtn)} )`);
})
.catch(err => {
console.log('error', err)
})

请求环境+请求地址定义

请求环境

  • 在 addr.js 中 env 变量定义

请求地址

  • 在 addr.js 中 addrList 统一管理所有请求地址

使用

1
2
import addrList from '../../addr';
const {apiConfig}=addrList;

react-native-scrollable-tab-view

  • 解决逗号影响的报错问题:在路径~/node_modules/react-native-scrollable-tab-viewSceneComponent.js 下删除即可

react-native 初始化报错,导致无法初始化

  • 重新设置一下地址
1
2
npm config set registry https://registry.npm.taobao.org
npm config set disturl https://npm.taobao.org/dist

动态切换状态

  • 采用对象的形式来操作,这样可以使用 state 里面的参数,来动态切换
  • 解决了直接应用的报错问题,以后遇到同样的问题要及时想到对象方式

声明周期-初始渲染 and 检测 goBack()

  • 为了保证页面的数据实时性,最好在初始的时候进行请求
1
componentDidMount(){}

检测 goBack()

需要重新加载 app

第一步

  • 在删除组件的时候,定义 goBack 事件
1
2
3
componentWillUnmount(){
DeviceEventEmitter.emit('goBack', 'goBack刷新返回页面数据');
}

第二步

  • 在初始渲染中监听,goBack 自定义事件
1
2
3
4
5
6
componentDidMount(){
// 接收
this.deEmitter = DeviceEventEmitter.addListener('goBack', (a) => {
this.loadData();
});
}

安卓打包

第一步:生成 Android 签名证书

第二步:设置 gradle 变量

  • 将你的签名证书 copy 到 android/app 目录下
  • 编辑~/.gradle/gradle.properties../android/gradle.properties(一个是全局 gradle.properties,一个是项目中的 gradle.properties,大家可以根据需要进行修改) ,加入如下代码:
1
2
3
4
MYAPP_RELEASE_STORE_FILE=ch09-keystore.jks
MYAPP_RELEASE_KEY_ALIAS=ch09-keystore
MYAPP_RELEASE_STORE_PASSWORD=123456
MYAPP_RELEASE_KEY_PASSWORD=123456

第三步:在 gradle 配置文件中添加签名配置

  • 编辑android/app/build.gradle文件添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
android {
...
defaultConfig { ... }
signingConfigs {
release {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
...

第四步:签名打包 APK

  • terminal 进入项目下的 android 目录,运行如下代码:
1
./gradlew assembleRelease
  • 签名打包成功后你会在 android/app/build/outputs/apk/目录下看到签名成功后的 app-release.apk 文件。
  • 提示:如果你需要对 apk 进行混淆打包 编辑 android/app/build.gradle:
1
2
3
4
5
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/

def enableProguardInReleaseBuilds = true

错误处理

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
34
fetch(apiLogin, {
method: 'POST',
headers: {
'Accept': 'application/json',//通过头指定,获取的数据类型是JSON
'Content-Type': 'application/json',
'Authorization':global.data.token,
},
body: JSON.stringify({
// 请求参数
})
})
.then(result => {
const {status,statusText} = result;
if(status>=200 && status<300 || status==304){
// 成功
const promise = result.json()
promise.then(rtn=>{
// 成功
})
}else if(status==403){
// 跳转登录
this.props.navigation.replace('login');
}else{
// 提醒 statusText
this.refs.toast.show(statusText);
}
})
.catch(error => {
if(Object.prototype.toString.call(error) === '[object Object]'){
this.refs.toast.show(JSON.stringify(error))
}else{
this.refs.toast.show(error)
}
})

app 的 logo and name

android

LOGO

  • 将 logo 分别放到 android/app/src/main/res 下的四个文件夹中,命名为 ic_launcher.png
  • 没有对应上的文件夹放一张1024*1024或者512*512的即可

app 名称

  • android/app/src/main/res/values/strings.xml中更改

IOS

LOGO

  • xcode> 根目录 >Images.xcassets 将生成的图标拖入对应的位置

app 名称

  • xcode> 根目录 >Info.plist 中修改 Bundlename 和 General> Display Name