React Native APP结构探索
APP结构探索
我在Github上找到了一个有登陆界面,能从网上获取新闻信息的开源APP,想来研究一下APP的结构。
附上原网址:我的第一个React Native App
具体来讲,就是研究一个复杂功能的APP在编写时是如何一步一步展开的,包括APP内部逻辑、与UI交互、与服务器交互等。
index.android.js
首先,我找到了index.android.js
文件。文件很短,内容如下:
/**
* News
* author : lufeng
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
var Route = require("./web_modules/route");
AppRegistry.registerComponent('News', () => Route);
可以看到,关键代码只有从"./web_modules/route"
调用的Route
,这也是整个程序的入口。
route.js
顺藤摸瓜找到了route.js
,代码比之前长了一点,如下:
/*
* 页面路由
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
BackAndroid,
Navigator,
Image,
Text,
View,
StatusBar
} from 'react-native';
var Tab = require("./tab");
var _navigator;
var Routes = React.createClass({
configureScence: function(){
return Navigator.SceneConfigs.FloatFromRight;
},
renderScene: function(route, navigator){
_navigator = navigator;
let Component = route.component;
return <Component route={route} navigator={navigator}/>
},
render: function(){
var renderScene = this.renderSceneAndroid;
var configureScence = this.configureScenceAndroid;
return (
<Navigator
initialRoute={{ name: '主页', component:Tab }}
configureScene={ this.configureScence }
renderScene={ this.renderScene}
/>
);
}
});
//监听硬件的back键操作
BackAndroid.addEventListener('hardwareBackPress', function() {
if(_navigator == null){
return false;
}
if(_navigator.getCurrentRoutes().length === 1){
return false;
}
_navigator.pop();
return true;
});
module.exports = Routes;
route.js
文件里的结构仍然很清晰,主要有三部分:
- 注册了名为
Routes
的组件。 - 监听
back
键操作并进行相应处理。 - 导出
Routes
。
React
允许将代码封装成组件(component
),然后像插入普通 HTML
标签一样,在网页中插入这个组件。React.createClass
方法就用于生成一个组件类。
Navigator
这里涉及到Navigator
的一些知识:
Navigator
即导航器,通过导航器我们可以实现应用在不同的页面之间进行跳转。
导航器会建立一个路由栈,用来弹出,推入或者替换路由状态。该路由栈相当于Android
原生中使用的任务栈。
renderScene
renderScene
方法就相当于我们使用的startActivity
方法了,我们可以在该方法中设置需要渲染的场景(跳转的页面),该方法接收两个参数(必要参数),route
和navigator
,其中route
就是路由的页面,navigator
是一个Navigator
对象,因为Navigator
对象拥有pop
,push
,jump
等方法,我们需要导航器对象来实现页面的跳转。而路由route
需要我们提前进行配置。
configureScene
该方法用来设置指定路由对象的配置信息,从而改变场景的动画或者手势。如:
configureScene={(route) => {
//跳转的动画
return Navigator.SceneConfigs.VerticalDownSwipeJump;
}}
initialRoute
用来设置默认页面,也就是启动APP看到的第一个页面,需要两个参数,name
和component
。
可以看到,这里设置的默认页面来自Tab
。而Tab
来自"./tab"
,我们打开tab.js
,重头戏好像来了!!因为我看到了很多写页面的代码。。。
tab.js
先贴代码:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Image,
Text,
View,
StatusBar
} from 'react-native';
import TabNavigator from 'react-native-tab-navigator'; //引入tabbar支持包
const TabNavigatorItem =TabNavigator.Item;
const TAB_ITEM = [{
code : 'Home',
name : '首页',
icon_n : require('./images/tab/tab_messagecenter_n.png'),
icon_p : require('./images/tab/tab_messagecenter_p.png'),
contentView : require('./tab_home')
},{
code : 'Suggest',
name : '推荐',
icon_n : require('./images/tab/tab_contact_n.png'),
icon_p : require('./images/tab/tab_contact_p.png'),
contentView : require('./tab_suggest')
},{
code : 'Find',
name : '发现',
icon_n : require('./images/tab/tab_discovery_n.png'),
icon_p : require('./images/tab/tab_discovery_p.png'),
contentView : require('./tab_find')
},{
code : 'Mine',
name : '我的',
icon_n : require('./images/tab/tab_myself_n.png'),
icon_p : require('./images/tab/tab_myself_p.png'),
contentView : require('./tab_mine')
}];
class Tab extends Component {
constructor(props){
super(props);
this.state = {
items : TAB_ITEM,
selectedTab : TAB_ITEM[0].code
}
}
/*
* tab点击方法
*/
onPress(tabCode){
if(tabCode){
this.setState({
selectedTab : tabCode
});
}
}
/*
*渲染每项
*/
renderTabView(options){
var tabNomal = options.icon_n;
var tabPress = options.icon_p;
return(
<TabNavigatorItem
key={options.code}
title={options.name}
renderIcon={()=><Image style={styles.tabIcon} source={tabNomal}/>}
renderSelectedIcon={()=><Image style={styles.tabIcon} source={tabPress}/>}
selected={this.state.selectedTab === options.code}
selectedTitleStyle={{color:'#333333'}}
onPress={()=>this.onPress(options.code)}
renderBadge= {()=>options.badgeNum?<View style={styles.badgeView}>
<Text style={styles.badgeText}>options.badgeNum</Text>
</View>:null}>
<options.contentView route={this.props.route} navigator={this.props.navigator}/>
</TabNavigatorItem>
);
}
render() {
var items = [];
for (var i=0; i< this.state.items.length; i++) {
items.push(this.renderTabView(this.state.items[i]));
}
return (
<View style={styles.container}>
<TabNavigator tabBarStyle={styles.tab}>
{items}
</TabNavigator>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
tab:{
height: 55,
alignItems:'center',
backgroundColor:'#f4f5f6',
},
tabIcon:{
width:25,
height:25,
},
badgeView:{
width:22,
height:14 ,
backgroundColor:'#f85959',
borderWidth:1,
marginLeft:10,
marginTop:3,
borderColor:'#FFF',
alignItems:'center',
justifyContent:'center',
borderRadius:8,
},
badgeText:{
color:'#fff',
fontSize:8,
}
});
module.exports = Tab;
这里看的比较费力。。先是创建了一个名为tab
的类,然后将界面底部的所有项的信息作为TAB_ITEM
传到tab
的constructor
中。接着是onPress()
方法作为tab
的点击方法,后面的renderTabView
方法的注释中标明了是渲染每项,其中又调用了TabNavigatorItem
组件,这个组件来自Github
。最后的render()
里就是加载了整个布局。
TabNavigator
Tab组件(底部导航):react-native-tab-navigator
https://github.com/exponentjs/react-native-tab-navigator
TAB_ITEM
这里以tab_home.js
为例,其他的类似。核心代码如下:
class Tab_Home extends Component {
constructor(props){
super(props);
}
showActionSheet(){
this.ActionSheet.show();
}
render() {
return (
<View style={{flex:1,justifyContent:'flex-start',alignItems:'center', bottom : 5}}>
<View style={styles.header}>
<View style={styles.header_btn}></View>
<View style={styles.header_center}>
<Text style={styles.header_title}>新闻网</Text>
</View>
<TouchableOpacity onPress={this.showActionSheet.bind(this)}>
<Image source={require('./images/header/more.png')} style={styles.header_icon,styles.header_btn}/>
</TouchableOpacity>
</View>
<Swiper style={styles.wrapper} showsButtons={false} autoplay={false} height={200} showsPagination={true}>
<Image style={styles.slide} source={ require('./images/demo/slideshow1.jpg') }></Image>
<Image style={styles.slide} source={ require('./images/demo/slideshow2.jpg') }></Image>
<Image style={styles.slide} source={ require('./images/demo/slideshow3.jpg') }></Image>
<Image style={styles.slide} source={ require('./images/demo/slideshow4.jpg') }></Image>
<Image style={styles.slide} source={ require('./images/demo/slideshow5.jpg') }></Image>
</Swiper>
<List dataNums="6" route={this.props.route} navigator={this.props.navigator}/>
<ActionSheet
ref={(o) => this.ActionSheet = o}
title="进入新闻推荐分类!"
options={buttons}
cancelButtonIndex={0}
destructiveButtonIndex={1}
/>
</View>
);
}
}
这个类主要是首页的布局,涉及到多种组件。其中比较值得一提的是TouchableOpacity
、Swiper
和ActionSheet
。
TouchableOpacity
本组件用于封装视图,使其可以正确响应触摸操作。当按下的时候,封装的视图的不透明度会降低。这个过程并不会真正改变视图层级,大部分情况下很容易添加到应用中而不会带来一些奇怪的副作用。(译注:此组件与TouchableHighlight
的区别在于并没有额外的颜色变化,更适于一般场景)
这里此组件的onPress()
事件的处理是弹出ActionSheet
菜单。
Swiper
用于组件(常见的是图片)的轮播。
官方文档:https://github.com/leecade/react-native-swiper
ActionSheet
从页面底部弹出菜单,拥有标题等属性,常用于应用的退出。本例是选择栏目用。(虽然没有实现具体的功能)
官方文档:https://github.com/beefe/react-native-actionsheet
今天就先到这啦。明天继续看~~
感谢以下几篇博客:
React Native APP结构探索的更多相关文章
- [译] Facebook:我们是如何构建第一个跨平台的 React Native APP
英文原文(需FQ):https://code.facebook.com/posts/1189117404435352/ 早些时候,我们介绍过iOS版的React Native. React Nativ ...
- React Native App设置&Android版发布
React Native系列 <逻辑性最强的React Native环境搭建与调试> <ReactNative开发工具有这一篇足矣> <解决React Native un ...
- React Native & app demos
React Native & app demos https://github.com/ReactNativeNews/React-Native-Apps https://github.com ...
- 利用 Create React Native App 快速创建 React Native 应用
本文介绍的 Create-React-Native-App 是非常 Awesome 的工具,而其背后的 Expo 整个平台也让笔者感觉非常的不错.笔者目前公司是采用 APICloud 进行移动应用开发 ...
- 我的第一个React Native App
我用了三天时间实现了一个相对比较完整的React Native 新闻发布类型的示例.应用做得很简单,但大多React Native的组件都有用到,今天做一个分享(由于我电脑是Windows系统,所以只 ...
- 用CodePush在React Native App中做热更新
最近在学React Native,学到了CodePush热更新. 老师讲了两种实现的方法,现将其记录一下. 相比较原生开发,使用React Native开发App不仅能节约开发成本,还能做原生开发不能 ...
- 利用 Create React Native App 创建 React Native 应用
$ npm i -g create-react-native-app $ create-react-native-app my-project $ cd my-project $ npm start
- 什么是 Native、Web App、Hybrid、React Native 和 Weex?(转载)
什么是 Native.Web App.Hybrid.React Native 和 Weex? 来源:zwwill_木羽 segmentfault.com/a/1190000011154120 一句 ...
- Native、Web App、Hybrid、React Native(简称RN)、Weex 间的异同点。
App常用开发模式简介 此处App为应用application,并非我们通常讲的手机App. 常用的几种APP开发模式-脑图 Native App 传统的原生App开发模式,有iOS和aOS两大系统, ...
随机推荐
- 前端构建大法 Gulp 系列 (二):为什么选择gulp
系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...
- CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果
CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...
- ABP源码分析四十四:ZERO的配置
ABP Zero模块中需要配置的地方主要集中在三块:配置静态的role,配置外部认证源,以及配置本地化语言和资源. UserManagementConfig/IUserManagementConfig ...
- Linux Nano命令
Nano命令指南 今天在输命令时,无意中输入了nano,对这个命令不太熟悉,结果不知道如何才能退出,保存,赶快查了一下资料,原来是这样的啊. 打开文件与新建文件 使用nano打开或新建文件,只需键入: ...
- AngularJs之八
***今天讲一下angularJs的路由功能: 一:angularJs路由. 1.AngularJS 路由允许我们通过不同的 URL 访问不同的内容. 2.通过 AngularJS 可以实现多视图的单 ...
- 解析大型.NET ERP系统 设计异常处理模块
异常处理模块是大型系统必备的一个组件,精心设计的异常处理模块可提高系统的健壮性.下面从我理解的角度,谈谈异常处理的方方面面.我的设计仅仅限定于Windows Forms,供参考. 1 定义异常类型 . ...
- <JavaScript语言精粹>--<读书笔记三>之replace()与正则
今天有人问我repalce(),他那个题目很有意思.我也不会做,于是我就去查,结果发现就是最基础的知识的延伸. 所以啊最基础的知识才是很重要的,千万不能忽略,抓起JS就写代码完全不知到所以然,只知道写 ...
- [C#] 走进异步编程的世界 - 在 GUI 中执行异步操作
走进异步编程的世界 - 在 GUI 中执行异步操作 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5877042.html 序 这是继<开始接 ...
- 11gRAC报错CRS-4535, CRS-4000解决
环境:AIX6.1 + Oracle11.2.0.4 RAC(2 nodes) 1.故障现象 2.定位问题 3.处理问题 1.故障现象 使用crsctl查看集群各资源状态,在任一节点都会直接报错CRS ...
- 探寻 JavaScript 逻辑运算符(与、或)的真谛
十二月已经过半,冬季是一个美妙的季节,寒冷的空气逼得人们不得不躲在安逸舒适的环境里生活.冬季会给人一种安静祥和的氛围,让人沉浸在其中,仿佛是一个旧的阶段的结束,同时也是一个新的阶段的开始.这么说来,西 ...