一、React Native配置环境
- React Native中文网: http://reactnative.cn/docs/0.41/getting-started.html
- React Native环境配置(简书):http://www.jianshu.com/p/ab07248f6741
二、引入第三方库 / 组件
第三方库引入
npm install name(三方库名) --save 安装的同时,将信息写入package.json中
组件引入(自定义组件)
import TextInputView from '../../components/EF_TextInputView'
三、setState渲染问题
每次调用this.setState,都会自动调用render函数,重新渲染一下界面。
(Tip:ListView如果使用这种方法,必须更改一下数据源,但不建议多次使用这种方式渲染界面,可以使用Mbox,学习网址:http://v.youku.com/v_show/id_XMjQ4NTA4OTUwOA==.html?spm=a2hzp.8253869.0.0&from=y1.7-2)
constructor(props) {
super(props);
this.state = {
isLoading: true, // 下拉刷新数据标记
};
}
_this.setState({
isLoading: false,
})
四、页面传值问题
1.直接传值
例如下侧代码中的 albumId= {this.props.albumId},=前面表示参数名,后面表示要传的数据。
<AlertCell
modalVisible={this.state.modalVisible}
navigator={this.props.navigator}
coverType= {this.props.coverType}
headerPhoto= {this.props.headerPhoto}
albumId= {this.props.albumId}
photosArr={photosArr}
dataArr={dataArr}
albumTitle={this.props.title1}
albumDesc={this.props.albumDesc}
{...this.props}
onClose={() => {
this.setState({modalVisible: false})
}}/>
2.跳转页面传值
使用Navigator进行页面跳转,进行传值时,
Navigator的使用
/*
* 设置Navigator转场方式
* */
configureScene = (route, routeStack) => {
if (route.type == 'bottom') {
return Navigator.SceneConfigs.FloatFromBottom; // 底部弹出
} else if (route.type == 'fade') {
return Navigator.SceneConfigs.FadeAndroid; // 淡入淡出
}
return Navigator.SceneConfigs.PushFromRight; // 右侧弹出
};
/*
* 传值
* */
renderScene = (route, navigator) => {
return <route.component navigator={navigator} {...route.passProps} />;//传值(使用时参数名passProps要与这里统一)
};
render() {
return (
<View style={{flex: 1}}>
<Navigator
style={{flex: 1}}
initialRoute={{component: Main}}//初始界面
configureScene={this.configureScene}
renderScene={this.renderScene}/>
{/*加载全局的顶部提示框组件*/}
<TopAlertBox />
</View>
)
}
传值
var navigator = this.props.navigator;
navigator.push({
title: '',
component: CreateAlbumView,
passProps: {
title1: '新建相册',
navigator: navigator,
data: this.data,
},
type: 'bottom'
})
3.反向传值
界面一:
var navigator = this.props.navigator;
navigator.push({
title: '新建相册',
component: CreateAlbumView,
passProps: {
title1: '',
navigator: navigator,
// 反向传值
getAlbum: function(albumData) {
albumArr.push(albumData);
_this.setState({
dataSource: ds.cloneWithRows(albumArr),
})
}
},
type: 'bottom'
})
界面二:
_this.props.getAlbum(albumData);
if (_this.props.navigator) {
_this.props.navigator.pop();
}
4.通知传值
引入RCTDeviceEventEmitter
import RCTDeviceEventEmitter from 'RCTDeviceEventEmitter'
设置监听
componentDidMount() {
let me = this;
// 删除相册
this.delete_listener = RCTDeviceEventEmitter.addListener('删除相册', function(albumId) {
for (let i = 0; i < albumArr.length; i++) {
if (albumArr[i].id === albumId) {
albumArr.splice(i, 1);
}
}
me.setState({
dataSource: ds.cloneWithRows(albumArr),
})
});
// 编辑相册
this.edit_listener = RCTDeviceEventEmitter.addListener('编辑相册', function(albumId, params) {
for (let i = 0; i < albumArr.length; i++) {
if (albumArr[i].id === albumId) {
albumArr[i].albumTitle = params.albumtitle;
albumArr[i].coverType = 1;
albumArr[i].albumCover = params.albumcover;
}
}
me.setState({
dataSource: ds.cloneWithRows(albumArr),
})
});
}
componentWillUnmount() {
this.delete_listener.remove();
this.edit_listener.remove();
}
发通知
RCTDeviceEventEmitter.emit('编辑相册', _this.state.albumId, params);
五、封装数据请求
/*
* post请求发送说说
* params:参数
* callback:回调函数
* */
static postShortposts(params, callback) {
url = API + 'shortposts/';
let paramsStr = '';
console.log('参数:' + JSON.stringify(params));
if (params) {
let paramsArray = [];
//拼接参数
Object.keys(params).forEach(key => paramsArray.push(key + '=' + params[key]))
paramsStr += paramsArray.join('&');
}
console.log('url: ' + url);
console.log('body: ' + paramsStr);
//fetch请求
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: paramsStr,
})
.then((response) => response.json())
.then((responseJSON) => {
callback(responseJSON)
}).done();
}
六、flex布局
对于学习过CSS的人,直接按照以前的方式理解就行
http://reactnative.cn/docs/0.41/layout-with-flexbox.html#content
七、this指向问题
this在RN中就是指这个类本身,但是经常会报一些错误:not an object(this.)或者not a funcation等,这类问题一般有两种解决办法
1.在render中里面调用方法的时候,使用this.方法名.bind(this),重新绑定一下this
2.在方法里面, let _this = this,使用_this来调用本身类
八、性能优化问题
1、声明方法函数时,要尽量使用 方法名= ()=> {},这样会减少方法引用的次数。然后在调用的时候,直接使用this.方法名即可。
2、只有 shouldComponentUpdate 返回true的时候才会更新页面。。比较this.props的isClicked属性(属性看自己情况而定)与newProps的isClicked属性是否相同。
shouldComponentUpdate(newProps, newState){
if(swllowArrayCompare(this.props.isClicked, newProps.isClicked)){
renturn true;
}
return false;
}
3、使用属性的时候,如果不需要重新渲染的属性,直接在state外面声明即可,调用的时候 this.属性名,这样就不会调用render函数了,不会重新渲染界面。
4、在render中使用const {属性}= this.prps,直接使用属性名就可以调用。这样可以不用再state里面使用了,减少了渲染的次数。
5、推迟render的过程,在数据请求完之后,使用InteractionManager.runAfterInteractions( ()=> {this.setStates({})})
6、使用mbox,只改变需要改变的,不重新全部渲染。