React Native入门-实战解析(上)
来自Leo的原创博客,转载请著名出处 我的stackoverflow 概述随着app端越来越复杂,迭代越来越快,很多app采用原生+html5的方式来实现,然后不知道什么时候,它就有了个高大上的名字 - hybrid app。类似的框架也很多,比较有名的有
这种app的原理是,用webview来实现类似原生的界面,也就是用h5写的代码是运行在webview里的。优点很明显
同样,缺点也很明显 - 性能相对较差(这一点在安卓上尤其明显,安卓的webview性能真的很差,而且安卓机型较多) React NativeReact native是facebook公司推出的一个app开发框架,facebook也有很多其他的框架,在这里都可以找到。
和上文提到的hybrid app最大的区别是 用Reactive Native开发的时候,实际运行的都是原生的代码 目前React Native支持
它的优点
如果你没有任何的JS和React基础可以先看看,我之前的这篇JS和React的基础文章 本文最终的效果本文的目的是实现一个从网络获取数据,加载到ListView,然后点击某一行可以跳转到详情页。 React Native环境搭建由于本文侧重的是如何使用React Native进行开发,所以并不会详细讲解如何安装和搭建环境。可以参考官方文档,搭建很简单 官方文档链接 有几点提一下
文档关于React Native的文档,在这里你都可以找到,这个系列我不会翻译facebook的文档。能阅读英文文档是程序员的一项基本技能,但是我会在使用的时候简单提一下 创建一个工程打开终端,cd到想要的目录去,然后 react-native init LeoRNWeather
可以看到生成了一个LeoRNWeather的文件夹,这个文件夹的默认的文件如下 android //安卓的工程
index.ios.js //iOS的程序入口文件
node_modules //
index.android.js //安卓的入口文件
ios //iOS的工程
package.json //全局的描述信息,本文就使用默认的了
对了我使用的IDE,是Atom 入门记住,React Native没有CSS,所有的实现都是JS的语法。当你打开 导入的模块,要先导入才能使用 import React,{
****
} from 'react-native';
样式布局定义,用JS的语法,由StyleSheet创建,其中样式使用了React的FlexBox,让布局变的十分简单 const styles = StyleSheet.create({
//*
welcome: {
fontSize: 20,textAlign: 'center',margin: 10,},//*
});
视图组件,视图继承自Component,可以在文档上找到很多Components class LeoRNWeather extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
</View>
);
}
}
可以看看这一行,可以看到React的视图语法和H5类似,标准的XML格式。 <Text style={styles.welcome}>
Welcome to React Native!
</Text>
!!!!我们删除这个文件里的全部内容,然后替换成React的风格代码 这时候代码如下 import React,{
AppRegistry,Component,StyleSheet,View,ListView,Text,} from 'react-native';
var LeoRNWeather = React.createClass({
render(){
return (
<View style= {styles.container}>
<Text style={styles.blackText}>这是一个标题</Text>
</View>
);
}
});
const styles = StyleSheet.create({
container: {
flex: 1,backgroundColor: 'white',justifyContent: 'center',blackText:{
fontSize:20,color:'rgb(0,0)',backgroundColor:'rgba(255,255,textAlign:'center',marginLeft:10,});
AppRegistry.registerComponent('LeoRNWeather',() => LeoRNWeather);
效果 添加导航栏这里提一下,在React Native中,导航栏有两种
本文使用 在顶部import引入 NavigatorIOS, 然后,重写
var LeoRNWeather = React.createClass({
render: function() {
return (
<NavigatorIOS
style={styles.container}
initialRoute={{
title: '主页',component: ListScreen,}}
/>
);
}
});
创建 var ListScreen = React.createClass({
render(){
return (
<View style= {styles.container}>
<Text style={styles.blackText}>blog.csdn.net/hello_hwc</Text>
</View>
);
}
});
然后, Save,选择模拟器,command+R刷新,可以看到效果(修改了文字) 添加背景图首先,在目录里添加一张图片
然后,将 import React,NavigatorIOS,Image,} from 'react-native';
var ListScreen = React.createClass({
render(){
return (
<Image source={require('./img/background.png')} style={styles.backgroundImg}>
<Text style={styles.whiteText}>blog.csdn.net/hello_hwc</Text>
</Image>
);
}
});
var LeoRNWeather = React.createClass({
render: function() {
return (
<NavigatorIOS
style={styles.container}
initialRoute={{
title: '主页',component: ListScreen,}}
/>
);
}
});
const styles = StyleSheet.create({
backgroundImg:{
flex:1,width: null,height: null,flexDirection: 'row',alignItems: 'center',whiteText:{
fontSize:20,color:'rgb(255,255)',textAlign:'left',container: {
flex: 1,});
AppRegistry.registerComponent('LeoRNWeather',() => LeoRNWeather);
效果图
关于Flexbox布局,可以参考这片文章,写的非常详细 进行网络请求React Native网络请求的文档可以在这里找到,在React中,网络请求使用Fetch, fetch('https://mywebsite.com/endpoint/',{ method: 'POST',headers: { 'Accept': 'application/json','Content-Type': 'application/json',body: JSON.stringify({ firstParam: 'yourValue',secondParam: 'yourOtherValue',}) })
由于网络请求是一个异步的请求,所以,它返回的是一个Promise对象,对于这个对象,有两种处理方式
由于本文是这个React Native系列的第一篇,所以处理方式采用同步处理。简单直接。 //Component挂载完毕后调用
componentDidMount() {
this.fetchData();
},fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json()) .then((responseData) => { }) .done(); },
这里的 var REQUEST_URL = 'https://raw.githubusercontent.com/LeoMobileDeveloper/React-Native-Files/master/person.json';
然后,save,command+R刷新模拟器,会发现Log如下 2016-04-21 13:53:49.563 [info][tid:com.facebook.React.JavaScript] [ { nickname: 'Leo',realname: 'WenchenHuang' },{ nickname: 'Jack',realname: 'SomethingElse' } ]
为了显示到ListView中,我们要把网络请求来的数据存储下来,为ListScreen添加如下方法
//自动调用一次,用来设置this.state的初始状态
getInitialState: function() {
return {
loaded: false,users: new ListView.DataSource({
rowHasChanged: (row1,row2) => row1 !== row2,}),};
},
然后修改fetchData方法,在加载完毕后保存数据 fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json()) .then((responseData) => { this.setState({ users: this.state.users.cloneWithRows(responseData),loaded: true,}); }) .done(); },
Tips:this.setState会触发render重新调用,进行重绘 写出一个列表移动开发中,列表是一个非常常用的控件。(iOS中的Tableview,android中的listview)。 ListView的文档链接
如何使用ListView
这时候的ListScreen类如下 var ListScreen = React.createClass({
getInitialState: function() {
return {
loaded: false,users: new ListView.DataSource({
rowHasChanged: (row1,row2) => row1 !== row2,componentDidMount() {
this.fetchData();
},fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json()) .then((responseData) => { this.setState({ users: this.state.users.cloneWithRows(responseData),render(){ if (!this.state.loaded) { return this.renderLoadingView() } return this.renderList() },renderLoadingView() { return ( <Image source={require('./img/background.png')} style={styles.backgroundLoading}> <ActivityIndicatorIOS style={[styles.centering,{height: 80}]} size="large" color="#ffffff" /> </Image> ); },renderList(){ return ( <Image source={require('./img/background.png')} style={styles.backgroundImg}> <ListView dataSource={this.state.users} renderRow={this.renderRow} style={styles.fullList} renderSeparator={(sectionID,rowID) => <View key={`${sectionID}-${rowID}`} style={styles.separator} />} /> </Image> ); },renderRow(user){ return ( <TouchableHighlight onPress={() => this.rowClicked(user)} underlayColor = '#ddd'> <View style={styles.rightCongtainer}> <Text style={styles.whiteText}>{user.nickname}</Text> <Text style={styles.whiteText}>{user.realname}</Text> </View> </TouchableHighlight> ); },rowClicked(user){ console.log(user); },});
Styles如下 const styles = StyleSheet.create({ backgroundImg:{ flex:1,width: null,height: null,flexDirection: 'row' },backgroundLoading:{ flex:1,alignItems: 'center',justifyContent: 'center',thumbnail: { width: 60,height: 60,rightCongtainer:{ flex:1,fullList:{ flex:1,paddingTop: 64,separator: { height: 0.5,backgroundColor: 'rgba(255,0.5)',centering: { alignItems: 'center',whiteText:{ fontSize:20,color:'rgb(255,backgroundColor:'rgba(255,textAlign:'left',marginLeft:10,blackText:{ fontSize:20,color:'rgb(0,textAlign:'center',container: { flex: 1,backgroundColor: 'white',});
这时候,save,command+R后,发现再网络请求的时候会先显示小菊花转转转,然后加载完毕之后,显示一个List 加载Spinner(仅适用于iOS)这个在上面的代码中提到了 renderLoadingView() {
return (
<Image source={require('./img/background.png')} style={styles.backgroundLoading}>
<ActivityIndicatorIOS style={[styles.centering, {height: 80}]} //风格 size="large" //大小 color="#ffffff" //颜色 />
</Image>
);
},
控制台打印上文的代码里提到 rowClicked(user){
console.log(user);
},
这时候,我们在点击某一行,会看到XCode中输出 在Chrome中调试使用Command+control+Z来调出调试窗口,然后选择
打开Chrome开发者工具 添加一个详情页,并且传值新建一个Component来表示详情页 var DetailScreen = React.createClass({
render(){
return (
<View style= {styles.container}>
<Text style={styles.blackText}>{this.props.user.nickname}</Text>
<Text style={styles.blackText}>{this.props.user.realname}</Text>
</View>
);
}
});
然后,在rowClick中,跳转到详情页 rowClicked(user){
console.log(user);
this.props.navigator.push({
title: "详情页",component: DetailScreen,passProps: {user:user},});
},
Tips:
简单提一下React Native的性能在RN中,主要有两个线程
其中,JavaScript是React Native的JS代码执行线程,React Native的触摸处理,网络请求,视图配置,以及app的业务逻辑都是发生在这里的。主线程是实际原生代码绘制视图的执行线程。使用React Native的时候,往往会遇到JavaScript线程执行逻辑过多,没有办法及时响应UI线程,导致掉帧.所以,React Native的性能,较纯原生的还是要差一些的 后续
附录,最终的 /**
* Sample React Native App
* https://github.com/facebook/react-native
*/
import React,ActivityIndicatorIOS,Navigator,TouchableHighlight,TouchableOpacity,} from 'react-native';
var REQUEST_URL = 'https://raw.githubusercontent.com/LeoMobileDeveloper/React-Native-Files/master/person.json';
var ListScreen = React.createClass({
getInitialState: function() {
return {
loaded: false,rowClicked(user){ console.log(user); this.props.navigator.push({ title: "详情页",}); },}); var DetailScreen = React.createClass({ render(){ return ( <View style= {styles.container}> <Text style={styles.blackText}>{this.props.user.nickname}</Text> <Text style={styles.blackText}>{this.props.user.realname}</Text> </View> ); } }); var LeoRNWeather = React.createClass({ render: function() { return ( <NavigatorIOS style={styles.container} initialRoute={{ title: '主页',}} /> ); } }); const styles = StyleSheet.create({ backgroundImg:{ flex:1,width: null,height: null,}); AppRegistry.registerComponent('LeoRNWeather',() => LeoRNWeather);
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Cocos2d-x3.12 Xcode打包spine\extension.h(89): fatal
- c# – 在MVC中声明html助手时,如何用破折号创建html属性?
- React-01-React概述
- Flex中如何使用A标签解决Text中给部分文字加连接的问题。
- cocos2d-x用shader来实现阴影
- 有关 flex.messaging.MessageException: Cannot create cla
- 使用Xml文档进行数据的保存的学生成绩管理系统
- ajax的简单应用
- alibaba fastjson(json序列化器)序列化部分源码解析-2-性能
- postgresql – 如何在Odoo 8中创建One2one关系?