样式的坑
1、 无 border: none
样式属性;
2、 StyleSheet.create()
创建了一个样式,在组件上使用时仅仅引用了一个id,所以如果你打印styles.name
,则会返回一个数字id;
- 创建一个样式表,就可以使得我们后续更容易通过ID来引用样式,而不是每次都创建一个新的对象。
- 它还使得样式只会在JavaScript和原生之间传递一次,随后的过程都可以只传递一个ID(这个优化还未实现)。
密钥库文件问题
在使用react-native-amap3d组件时,需要注册高德key,出现以下问题:
[keytool 错误: java.lang.Exception: 密钥库文件不存在: keystore]
参考地址:https://blog.csdn.net/Newsolider2012/article/details/52401735
第一步、生成keystore文件
keytool
属于java jdk的一个工具,我们可以利用这个去生成密钥文件;
- 打开cmd, 使用命令
cd 你的java安装目录/java/jdk/bin
,进入keytool可执行文件的路径; - 执行
keytool -genkey -alias key文件别名 -keyalg RSA -validity 20000 -keystore geom.keystore
,会出现接下来的界面:
在bin目录下会生成对应的.keystore文件,此文件就是你的签名文件;
第二步、在项目中应用keystore
打开你的Android项目的build.gradle
,将keystore文件绑定到项目中:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
signingConfigs {
release {
keyAlias 'geom'
keyPassword 'lfreformer'
storeFile file('E:/GeomDebug/android/keystores/geom.keystore')
storePassword 'lfreformer'
}
debug {
keyAlias 'geom'
keyPassword 'lfreformer'
storeFile file('E:/GeomDebug/android/keystores/geom.keystore')
storePassword 'lfreformer'
}
}
}
第三步、获取KeyStore指纹信息
打开Android studio 的控制台;执行命令:keytool -list -v -keystore E:\GeomDebug\android\keystores\geom.keystore(这儿需要你替换成自己的keystore文件路径)
注意:最后是你keystore文件存放位置;最后获取结果:
其中SHA1
值就是需要的在高德地图中填写的内容。
模拟数据
由于项目开发过程中前端独立开发阶段需要自己模拟本地数据,所以就引出一个问题,react-native的模拟数据放置在哪,如何请求。
其实react-native启动时会在项目根目录默认开一个端口号为8081的server,所以只需将mock数据放置在项目根目录进行请求即可。
我的模拟数据目录:
请求示例:1
fetch('http://localhost:8081/mock/xx.json').then(...)
Api方式动态添加元素
在开发过程中会遇到自定义toast
,alert
等需要通过api方式(eg: Toast.show()
)全局显示的组件,这个时候要动态添加组件,并且必须是全局组件的属性,在react-native中如何实现,这个时候需要用到AppRegistry
的setWrapperComponentProvider
方法: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
29import React, { Component } from 'react';
import { View, Text, AppRegistry } from 'react-native';
AppRegistry.setWrapperComponentProvider(function() {
return class extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={{flex: 1}}>
{this.props.children}
<View
style={{
width: 200,
height: 500,
backgroundColor: 'red',
position: 'absolute',
zIndex: 1000,
top: 45,
left: 0
}}
/>
</View>
)
}
}
})
注意:
AppRegistry.setWrapperComponentProvider
不可用在组件生命周期内,必须全局/模块中使用;- return的组件中必须包裹
{this.props.children}
,这个子组件代表你每页的组件,而内部包含的View组件就是你动态添加的组件;
Android端双击物理返回键退出应用
api: BackHandler; 示例: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
35export default function (WrappedComponent) {
return class extends Component {
constructor(props) {
super(props);
this._onBackAndroid = this._onBackAndroid.bind(this);
}
componentWillMount(){
BackHandler.addEventListener('hardwareBackPress', this._onBackAndroid);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this._onBackAndroid);
}
render() {
return (
<WrappedComponent {...this.props} backHandler={this._onBackAndroid} />
)
}
_onBackAndroid() {
if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
//最近2秒内按过back键,可以退出应用。
return false;
}
this.lastBackPressed = Date.now();
ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT);
return true;
}
}
}
示例为react高阶函数组件,可包裹用于任意组件;
存在问题:
首页组件不会触发componentWillUnmount
生命周期,所以会导致在首页后打开的任意页面物理返回键均会触发“再按一次退出应用”,在react-navigation中,修改为如下方式: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
34componentDidMount() {
this.getParkData();
this.didFocusSubscription = this.props.navigation.addListener(
'didFocus',
payload => {
BackHandler.addEventListener('hardwareBackPress', this.props.backHandler);
this.getStorage().then(data => {
if (data) {
data = JSON.parse(data);
AsyncStorage.removeItem('selectPark');
this.locate(data, this.showInfoWindow.bind(this, data));
}
})
}
);
this.willBlurSubscription = this.props.navigation.addListener(
'willBlur',
payload => {
BackHandler.removeEventListener('hardwareBackPress', this.props.backHandler);
}
);
}
componentWillUnmount() {
if (this.didFocusSubscription) {
this.didFocusSubscription.remove();
}
if (this.willBlurSubscription) {
this.willBlurSubscription.remove();
}
}
以上通过监听react-navigation
提供的事件进行BackHandler
的处理;
修改打包后应用名
默认应用名会是应用初始化时的文件名;修改方式:
- 进入
android/app/src/main/AndroidManifest.xml
; - 找到
android:label="@string/app_name"
,这个就代表的是应用名(引用第三步文件内的值); - 进入
android/app/src/main/res/valuse/strings.xml
; - 修改如下代码:
1
2
3<resources>
<string name="app_name">你的APP名称</string>
</resources>