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客户端
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories