您的位置:首页 > Web前端 > React

React Native学习笔记之一

2016-07-05 18:25 756 查看

概述:

React Native 是现在比较火的Android APP开发技术,由FaceBook推出的基于JSX开发的一个可以跨平台开发的框架。 Facebook在这个框架中提出了一个理念: Learn once, write anywhere 也是这个框架的优势所在。目前基于RN开发的APP有:

天猫iPad客户端,支付宝,携程网,Facebook Group,Chinese Flashcards等等(部分业务、模块采用RN开发)。

下图是RN实践的demo:



Step 1: 环境的搭建(mac)

安装Homebrew;

安装nvm;

安装node,通过命令:
nvm install node && nvm alias default node


安装watchmam,通过命令:
brew install watchman


安装flow,通过命令:
brew install flow


安装React Native,通过命令:
npm install -g react-native-cli
;

创建React Native应用程序,通过命令
react-native init HelloWorld
;

进入HelloWorld目录,并创建5.0系统以上的安卓模拟器;

配置React Native环境,通过命令
npm install


运行React Native程序,通过命令
react-native run-android


Step 2: React Native项目的基本认识

进入HelloWorld目录后,我们至少看到以下几个文件或者文件夹:

文件夹

android

ios

node_modules

文件

index.androi.js

index.ios.js

package.json

android、ios文件夹分别对应ios工程和android工程,两个js文件分别对应android、ios默认的js文件,package.json和package.json是React Native的环境配置相关文件。

Android工程依赖于指定的js展示界面,全工程甚至可以只需要通过一个Activity和多个js文件来表现不同的页面。在js文件中,Facebook提供了UI组件,网络请求等其他APIS,类似于于Activity+XML的结合体。

在这里不得不提的是,Facebook在最早的时候提出基础理念叫做React,基于此出现了ReactJS来开发网页,直到现在出现React Native来开发移动应用。在React Native官网中提到这么一句话:

React Native enables you to build world-class application experiences on native platforms using a consistent developer experience based on JavaScript and React.


也就是说React Native是基于JavaScript和React的开发框架,因此支持JS语法。

Step 3: JS文件语法的初步学习

打开index.androoid.js,观察里面的代码。从上往下解读:

代码的开始以:

import ... from ...


的方式引入该界面所需要的组件元素。

中间创建了一个HelloWorld组件,在最早的RN版本中,使用
React.CreateClass
的形式创建组件,在最新的RN版本中使用了:

extends Component


的方式代替
React.CreateClass
,因此在很多教程中出现不一样的代码。

接下来是

const styles = StyleSheet.create({})


这里才用CSS Style来对UI进行管理。

最后

AppRegistry.registerComponent('HelloWorld', () => HelloWorld);


注册组件,单引号内的HelloWorld对应MainActivity中的
getMainComponentName()
方法返回的指定的组件名称,后面的HelloWorld是我们在上面通过
extends Component
的方式创建的component。

重点观察
class HelloWorld
中的内容:

render() {
return {};
};


在render方法中返回了类似于“div”标签形式组合的ui组件,通过修改对应的文本,并双击R(Genymotion)ReLoad JS,可以查看修改后的内容。

通过访问React Native官网,在左侧的导航列表的
COMPONENTS
列表中可以看到通用的UI控件,如
ListView
Image
等等。参考官网提供的学习步骤,我们可以新建一个js文件,建立自己的Movie List程序,效果图如上图所示。

Step 4: JS文件的编写

新建movielist.js,并保存在目录HelloWorld工程的根目录下(与index.android.js目录平级),修改MainActivity中的
getJSMainModuleName()
方法返回的String字符串
"index.android"
"movielist"
,引入相应控件,
Image
Text
等:

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
} from 'react-native';


创建HelloWorld组件,完成
render()
方法,返回movie list程序的第一个item:

class HelloWorld extends Component{

render() {
return {
<View style={styles.item}>
<ImageView style={style.img} source={{require('./img/icon.png'})} />
<Text style"styles.text">movie item</Text>
</View>
}
}

}

const styles = StyleSheet.create({
item: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
padding: 10,
},
img: {
width: 100,
height: 100,
justifyContent: 'center',
},
text: {
width: 200,
fontSize: 10,
textAlign: 'left',
}
});


其中style属性同CSS的应用方法大同小异,可以查阅官网左侧导航栏底部的
POLYFILLS
导航进行查阅。

Image组件设置图片的方式两种,

本地:`source={require('./img/icon.png')}`;
网络:`source={{uri: item.url}}`


如果想获取到屏幕的宽度或者高度来控制控件的宽高,可通过
Dimensions
:

import {
Dimensions
} from 'react-native';

const styles = StyleSheet.create({
text: {
width: Dimensions.get('window').width - 150,
fontSize: 10,
textAlign: 'left',
}
});


item编写完成后,导入ListView组件,完成ListView的编写:

ListView是需要数据源和item view的,因此修改刚才编写好的代码,将
render()
方法中返回的UI组件抽取为
rendItem()
方法,并重写
render()
方法

import { ListView } from 'react-native';

class HelloWorld extends Component{

render() {
return {
<ListView
dataSouce={}
renderRow={this.renderItem}
></ListView>
}
}

renderItem(){
return {
<View style={styles.item}>
<ImageView style={style.img} source={{require('./img/icon.png'})} />
<Text style"styles.text">movie item</Text>
</View>
}
}

}


继续为ListView补充数据,采用从网络获取的方式,Facebook提供了fetch()函数进行异步网络请求:

var REQUEST_URL = "https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json"

class HelloWorld extends Component{

constructor() {
super();
this.state = {
dataSource: new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2 })
};
}

componentDidMount() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
});
})
.done()
}

}


在这里,
constructor()
componentDidMount()
render()
方法一样,为RN组件的生命周期,在通过

constructor()
声明数据,
componentDidMount()
方法进行数据设置,调用this.setState()方式强制重新调起
render()
方法刷新视图。在
React.createClass
的语法中,
constructor()
方法等同
getInitialState()


方法,都是用来初始化状态值,可用来改变组件状态。

componentDidMount()
方法中通过
fetch(REQUEST_URL)
得到相应值
response
并进行转化为相应的数据格式,取对应的值赋值
dataSource


注意这里的
dataSource
必须通过:

dataSource: new ListView.DataSource({rowHasChanged: (row1, row2) => row1 !== row2 })


的方式进行初始化,
rowHasChanged
是ListView的dataSource的必须属性,用来进行渲染的优化,类似于ViewHolder。

补全代码,并修改item的数据:

render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderItem}>
</ListView>
)

renderItem(movie){
return {
<View style={styles.item}>
<ImageView style={style.img} source={{uri: movie.posters.thumbnail}} />
<Text style"styles.text">{movie.title}</Text>
</View>
}
}
}


至此,movie list程序已经基本完成,接下来添加点击item的点击事件。这里我们采用组件:TouchableHighlight。修改
renderItem(movie)
方法:

renderItem(movie){
return {
<TouchableHighlight onPress={this.alertImage}>
<View style={styles.item}>
<ImageView style={style.img} source={{uri: movie.posters.thumbnail}} />
<Text style"styles.text">{movie.title}</Text>
</View>
</TouchableHighlight>
}
}

alertImage(){
alert("点击了一条item");
}


Facebook一共提供了四个Android的点击组件,基本点击组件为
TouchableWithoutFeedback
,其余的点击组件可以视为由
TouchableWithoutFeedback
发展过来的,
TouchableWithoutFeedback
是无点击出发效果的控件,而诸如
TouchableHighlight
则是可以通过style配置点击的动画背景效果的,可以通过TouchableWithoutFeedback等查询相应的属性。

同时,点击事件提供了按下时、松开后、长按、短按四个动作事件,同样在API上查询到,并且要注意的是:
onPress
的执行者是一个Object,而不是调用
this.alertImage()
,这是不被允许的语法。

上面我们写了最简单的点击事件,但是并没有出现对应的效果,经过查询原因,发现
this.alertImage()
的作用域并不正确。这里的
this
并不是指代的事我们认为的组件this,而是在执行
renderRow={this.renderItem()}
的时候改变了this的指向,因此我们可以通过
bind()
方法来修正这一个错误:

render() {
return {
<ListView
dataSouce={}
renderRow={this.renderItem.bind(this)}
></ListView>
}
}


重新运行,发现点击之后会弹出一个弹出框。但是如果想传递点击条目对应的数据,这个时候我们发现因为只能通过Object指定点击事件,所以我们不能像调用方法那样补写参数。这个时候,我们同样可以用
bind()
方法实现目的:

renderItem(movie){
return {
<TouchableHighlight onPress={this.alertImage.bind(this,movie)}>
<View style={styles.item}>
<ImageView style={style.img} source={{uri: movie.posters.thumbnail}} />
<Text style"styles.text">{movie.title}</Text>
</View>
</TouchableHighlight>
}
}

alerImage(movie) {
alert(movie.id);
}


Step 5: 总结

通过简单的初步的学习,我们了解了大致的RN应用程序交互是如何实现的。简单来说是Facebook提供了一套js解析库,开发者通过创建RN工程编写JS文件由JS库解析得到相应的事件动作。因此学习的方向包括组件的应用及封装,API和RN生命周期的学习。

在这里推荐可以学习研究的Demo:

Demo: Reading

干货集中营

OSChina的Git@OSC客户端
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android React native